亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

JSON 字符串的交集

JSON 字符串的交集

Go
嚕嚕噠 2023-04-17 16:46:28
我試圖找到一種方法來使用一個 JSON 字符串作為各種“模板”以應用于另一個 JSON 字符串。例如,如果我的模板如下所示:{   "id": "1",   "options": {      "leatherseats": "1",      "sunroof": "1"   }}然后我將其應用于以下 JSON 字符串:{   "id": "831",   "serial": "19226715",   "options": {      "leatherseats": "black",      "sunroof": "full",      "fluxcapacitor": "yes"   }}我想要一個生成的 JSON 字符串,如下所示:{   "id": "831",   "options": {      "leatherseats": "black",      "sunroof": "full",   }}不幸的是,我既不能依賴模板也不能依賴固定格式的輸入,所以我不能編組/解組到定義的接口中。我編寫了一個遍歷模板的遞歸函數,以構造一段字符串,其中包含要包含的每個節點的名稱。func traverseJSON(key string, value interface{}) []string {    var retval []string    unboxed, ok := value.(map[string]interface{})    if ok {        for newkey, newvalue := range unboxed {            retval = append(retval, recurse(fmt.Sprintf("%s.%s", key, newkey), newvalue)...)        }    } else {        retval = append(retval, fmt.Sprintf("%s", key))    }    return retval}我調用這個函數如下:template := `my JSON template here`var result map[string]interface{}json.Unmarshal([]byte(template), &result)var nodenames []stringnodenames = append(nodenames, traverseJSON("", result)...)然后我打算編寫第二個函數,它使用節點名稱的這一部分從輸入的 JSON 字符串構造一個 JSON 字符串,但我失去了動力,開始認為我可能走錯了路。對此的任何幫助將不勝感激。
查看完整描述

1 回答

?
函數式編程

TA貢獻1807條經驗 獲得超9個贊

只需創建一個基于模板和源地圖“克隆”地圖的功能。

該解決方案將遍歷模板映射的條目,并為每一(k, v)對在目標映射中生成一個條目,如下所示:

  • 如果不是映射,只需從源映射中v獲取鍵的值,并在目標中使用它。k

  • 如果v也是一個地圖,則遞歸地調用此“克隆器”,新模板地圖是v,新源是鍵的源的值k。k此遞歸調用的結果將是目標映射中鍵的值。

這就是它的樣子:

func procMap(tmpl, src map[string]interface{}) (dst map[string]interface{}) {

? ? dst = map[string]interface{}{}


? ? for k, v := range tmpl {

? ? ? ? if innerMap, ok := v.(map[string]interface{}); ok {

? ? ? ? ? ? dst[k] = procMap(innerMap, src[k].(map[string]interface{}))

? ? ? ? } else {

? ? ? ? ? ? dst[k] = src[k]

? ? ? ? }

? ? }


? ? return dst

}

就這樣。


測試它:


// tmpljson is the template JSON

var tmpl map[string]interface{}

if err := json.Unmarshal([]byte(tmpljson), &tmpl); err != nil {

? ? panic(err)

}


// srcjson is the source JSON

var src map[string]interface{}

if err := json.Unmarshal([]byte(srcjson), &src); err != nil {

? ? panic(err)

}


dst := procMap(tmpl, src)


enc := json.NewEncoder(os.Stdout)

enc.SetIndent("", "? ")

if err := enc.Encode(dst); err != nil {

? ? panic(err)

}

使用示例 JSON 輸出(在Go Playground上嘗試):


{

? "id": "831",

? "options": {

? ? "leatherseats": "black",

? ? "sunroof": "full"

? }

}

筆記:


該解決方案假定源映射符合模板。也就是說,如果模板包含某個鍵的映射,則源映射也應包含相同鍵的映射。如果不能保證這一點,procMap()則應通過檢查來擴展該函數以避免運行時恐慌,如下所示:


for k, v := range tmpl {

? ? if innerMap, ok := v.(map[string]interface{}); ok {

? ? ? ? if src2, ok2 := src[k].(map[string]interface{}); ok2 {

? ? ? ? ? ? dst[k] = procMap(innerMap, src2)

? ? ? ? } else {

? ? ? ? ? ? log.Printf("src is not conform to template at key %q", k)

? ? ? ? }

? ? } else {

? ? ? ? dst[k] = src[k]

? ? }

}

另請注意,JSON 數組(切片)不會以任何特殊方式處理,這意味著如果模板包含切片,則源中的值將按原樣使用,如果切片包含映射,則不會發生遞歸。

查看完整回答
反對 回復 2023-04-17
  • 1 回答
  • 0 關注
  • 164 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號