以下是我需要的一个例子:
默认JSON:
{
"name": "John",
"greetings": {
"first": "hi",
"second": "hello"
}
}
与更改合并:
{
"name": "Jane",
"greetings": {
"first": "hey"
}
}
应该成为:
{
"name": "Jane",
"greetings": {
"first": "hey",
"second": "hello"
}
}
以下是我尝试的内容:
package main
import (
"encoding/json"
"fmt"
"reflect"
)
func MergeJSON(defaultJSON, changedJSON string) string {
var defaultJSONDecoded map[string]interface{}
defaultJSONUnmarshalErr := json.Unmarshal([]byte(defaultJSON), &defaultJSONDecoded)
if defaultJSONUnmarshalErr != nil {
panic("Error unmarshalling first JSON")
}
var changedJSONDecoded map[string]interface{}
changedJSONUnmarshalErr := json.Unmarshal([]byte(changedJSON), &changedJSONDecoded)
if changedJSONUnmarshalErr != nil {
panic("Error unmarshalling second JSON")
}
for key, _ := range defaultJSONDecoded {
checkKeyBeforeMerging(key, defaultJSONDecoded[key], changedJSONDecoded[key], changedJSONDecoded)
}
mergedJSON, mergedJSONErr := json.Marshal(changedJSONDecoded)
if mergedJSONErr != nil {
panic("Error marshalling merging JSON")
}
return string(mergedJSON)
}
func checkKeyBeforeMerging(key string, defaultMap interface{}, changedMap interface{}, finalMap map[string]interface{}) {
if !reflect.DeepEqual(defaultMap, changedMap) {
switch defaultMap.(type) {
case map[string]interface{}:
//Check that the changed map value doesn't contain this map at all and is nil
if changedMap == nil {
finalMap[key] = defaultMap
} else if _, ok := changedMap.(map[string]interface{}); ok { //Check that the changed map value is also a map[string]interface
defaultMapRef := defaultMap.(map[string]interface{})
changedMapRef := changedMap.(map[string]interface{})
for newKey, _ := range defaultMapRef {
checkKeyBeforeMerging(newKey, defaultMapRef[newKey], changedMapRef[newKey], finalMap)
}
}
default:
//Check if the value was set, otherwise set it
if changedMap == nil {
finalMap[key] = defaultMap
}
}
}
}
func main() {
defaultJSON := `{"name":"John","greetings":{"first":"hi","second":"hello"}}`
changedJSON := `{"name":"Jane","greetings":{"first":"hey"}}`
mergedJSON := MergeJSON(defaultJSON, changedJSON)
fmt.Println(mergedJSON)
}
上面的代码返回以下内容:
{
"greetings": {
"first": "hey"
},
"name": "Jane",
"second": "hello"
}
所以基本上任何更改都应该应用于默认值并返回完整的JSON。我还需要这个递归工作。
我该如何解决这个问题?我可以看到我出错的地方,我不知道如何让它以递归方式工作。
由于
答案 0 :(得分:1)
发布的代码中的问题与您的递归调用有关:
checkKeyBeforeMerging(newKey, defaultMapRef[newKey], changedMapRef[newKey], finalMap)
对finalMap
的引用实际上应该是合并地图的嵌套部分。含义用finalMap
替换finalMap[key].(map[string]interface{})
。
答案 1 :(得分:0)
我最近遇到了同样的需求,这是我的解决方案:
// override common json by input json
func Override(input, common interface{}) {
switch inputData := input.(type) {
case []interface{}:
switch commonData := common.(type) {
case []interface{}:
for idx, v := range inputData {
Override(v, commonData[idx])
}
}
case map[string]interface{}:
switch commonData := common.(type) {
case map[string]interface{}:
for k, v := range commonData {
switch reflect.TypeOf(v).Kind() {
case reflect.Slice, reflect.Map:
Override(inputData[k], v)
default:
// do simply replacement for primitive type
_, ok := inputData[k]
if !ok {
inputData[k] = v
}
}
}
}
}
return
}
在调用前解组json:
var commmon interface{}
if err = json.Unmarshal("common data", &commmon); err != nil {
logger.Error(err)
return
}
var input interface{}
if err = json.Unmarshal("input data", &input); err != nil {
logger.Error(err)
return
}
Override(input, commmon)