Here's an example of what I need:
Default JSON:
{
"name": "John",
"greetings": {
"first": "hi",
"second": "hello"
}
}
merged with the changes:
{
"name": "Jane",
"greetings": {
"first": "hey"
}
}
should become:
{
"name": "Jane",
"greetings": {
"first": "hey",
"second": "hello"
}
}
Here's what I've tried:
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)
}
The code above returns the following:
{
"greetings": {
"first": "hey"
},
"name": "Jane",
"second": "hello"
}
So basically any changes should be applied to the default and return the full JSON. I also need this to work recursively.
How can I fix this? I can see where I went wrong, I'm just not sure how to make it work recursively.
Thanks