package testhelper import ( "encoding/json" "fmt" ) type JSONComparer struct { result map[string]interface{} IgnoreProps []string } func (j *JSONComparer) Close() { j.result = nil j.IgnoreProps = nil } func (j *JSONComparer) GetDiff(reference []byte, compare []byte) (map[string]interface{}, error) { j.result = map[string]interface{}{} objRef := map[string]interface{}{} objComp := map[string]interface{}{} err := json.Unmarshal(reference, &objRef) if err != nil { return j.result, err } err = json.Unmarshal(compare, &objComp) if err != nil { return j.result, err } j.compare("", objRef, objComp) return j.result, nil } func (j *JSONComparer) isMap(obj interface{}) (converted map[string]interface{}, isMap bool) { converted, isMap = obj.(map[string]interface{}) return } func (j *JSONComparer) isIgnored(key string) bool { for _, ignored := range j.IgnoreProps { if ignored == key { return true } } return false } func (j JSONComparer) processMap(key string, refVal interface{}, compVal interface{}) bool { if convRef, isRefMap := j.isMap(refVal); isRefMap { if convCom, isComMap := j.isMap(compVal); isComMap { j.compare(fmt.Sprintf("%s.", key), convRef, convCom) return true } } return false } func (j *JSONComparer) compare(prefix string, reference map[string]interface{}, compare map[string]interface{}) { for key, refVal := range reference { if j.isIgnored(key) { continue } if comVal, ok := compare[key]; !ok { j.result[key] = "missing" } else { if j.processMap(key, refVal, comVal) { continue } if comVal != refVal { j.result[prefix+key] = refVal } } } }