只需创建一个基于模板和源地图“克隆”地图的函数。
该解决方案将遍历模板映射的条目,并为每一
(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 JSonvar tmpl map[string]interface{}if err := json.Unmarshal([]byte(tmpljson), &tmpl); err != nil { panic(err)}// srcjson is the source JSonvar src map[string]interface{}if err := json.Unmarshal([]byte(srcjson), &src); err != nil { panic(err)}dst := procMap(tmpl, src)enc := json.NewEnprer(os.Stdout)enc.SetIndent("", " ")if err := enc.Enpre(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数组(切片)不会以任何特殊方式处理,这意味着如果模板包含切片,则按原样使用源中的值,并且如果切片包含地图,则不会进行递归。该解决方案也可以轻松扩展为处理切片,这留给读者练习。



