handlename's blog

コード片など

goでJSONを比較したい場合

JSONでデータをやりとりするパッケージで、 得られるJSONが期待するものかどうかをテストするときにどうすればいいのか、という話。

ググってもこれといったものが見つけられなかったので interface{}な変数にjson.Unmarshalしてからreflect.DeepEqualしてみたら うまく動いていそうな感じだったのでここに記す。

実際に使う場合はどのキーの値が間違ってる、とか このキーが余計、とかがわかったほうが親切なんだけど、 それをやるとなるとreflect.DeepEqualじゃなくて 自分で再帰して比較する処理を書かないといけなそう。

http://play.golang.org/p/x_TtCRnHjv

以下はplaygroundと同じコードと出力。

コード

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

func DeepEqualJSON(j1, j2 string) (error, bool) {
    var err error

    var d1 interface{}
    err = json.Unmarshal([]byte(j1), &d1)

    if err != nil {
        return err, false
    }

    var d2 interface{}
    err = json.Unmarshal([]byte(j2), &d2)

    if err != nil {
        return err, false
    }

    if reflect.DeepEqual(d1, d2) {
        return nil, true
    } else {
        return nil, false
    }
}

func IsEqualJSON(a, b string) {
    err, r := DeepEqualJSON(a, b)

    if err != nil {
        fmt.Printf("error: %s\n", err)
    } else if r {
        fmt.Printf("ok: %s == %s\n", a, b)
    } else {
        fmt.Printf("ng: %s != %s\n", a, b)
    }

}

func IsNotEqualJSON(a, b string) {
    err, r := DeepEqualJSON(a, b)

    if err != nil {
        fmt.Printf("error: %s\n", err)
    } else if r {
        fmt.Printf("ng: %s == %s\n", a, b)
    } else {
        fmt.Printf("ok: %s != %s\n", a, b)
    }
}

func main() {
    IsEqualJSON(`{}`, `{}`)
    IsEqualJSON(`{"a":"hoge"}`, `{"a":"hoge"}`)
    IsNotEqualJSON(`{"a":"hoge"}`, `{"a":"fuga"}`)
    IsNotEqualJSON(`{"a":"hoge"}`, `{"b":"hoge"}`)

    IsEqualJSON(`{"a":"hoge","b":"fuga"}`, `{"b":"fuga","a":"hoge"}`)

    IsEqualJSON(`{"a":{"aa":1}}`, `{"a":{"aa":1}}`)
    IsNotEqualJSON(`{"a":{"aa":1}}`, `{"a":{"aa":2}}`)

    IsEqualJSON(`{"a":{"aa":1,"bb":2}}`, `{"a":{"bb":2,"aa":1}}`)
    IsNotEqualJSON(`{"a":{"aa":1,"bb":2}}`, `{"a":{"aa":1,"bb":1}}`)

    IsEqualJSON(`{"a":[1,2]}`, `{"a":[1,2]}`)
    IsNotEqualJSON(`{"a":[1,2]}`, `{"a":[2,1]}`)

    IsEqualJSON(`{"a":[1,2],"b":{"bb":3}}`, `{"a":[1,2],"b":{"bb":3}}`)
    IsNotEqualJSON(`{"a":[1,2],"b":{"bb":3}}`, `{"a":[1,2],"b":{"bb":4}}`)

    IsEqualJSON(`{"a":{"b":{"c":{"d":0}}}}`, `{"a":{"b":{"c":{"d":0}}}}`)
    IsNotEqualJSON(`{"a":{"b":{"c":{"d":0}}}}`, `{"a":{"b":{"c":{"d":1}}}}`)

    IsEqualJSON(`[]`, `[]`)
    IsEqualJSON(`[{"a":1}]`, `[{"a":1}]`)
    IsNotEqualJSON(`[{"a":1}]`, `[{"a":2}]`)
}

出力

ok: {} == {}
ok: {"a":"hoge"} == {"a":"hoge"}
ok: {"a":"hoge"} != {"a":"fuga"}
ok: {"a":"hoge"} != {"b":"hoge"}
ok: {"a":"hoge","b":"fuga"} == {"b":"fuga","a":"hoge"}
ok: {"a":{"aa":1}} == {"a":{"aa":1}}
ok: {"a":{"aa":1}} != {"a":{"aa":2}}
ok: {"a":{"aa":1,"bb":2}} == {"a":{"bb":2,"aa":1}}
ok: {"a":{"aa":1,"bb":2}} != {"a":{"aa":1,"bb":1}}
ok: {"a":[1,2]} == {"a":[1,2]}
ok: {"a":[1,2]} != {"a":[2,1]}
ok: {"a":[1,2],"b":{"bb":3}} == {"a":[1,2],"b":{"bb":3}}
ok: {"a":[1,2],"b":{"bb":3}} != {"a":[1,2],"b":{"bb":4}}
ok: {"a":{"b":{"c":{"d":0}}}} == {"a":{"b":{"c":{"d":0}}}}
ok: {"a":{"b":{"c":{"d":0}}}} != {"a":{"b":{"c":{"d":1}}}}
ok: [] == []
ok: [{"a":1}] == [{"a":1}]
ok: [{"a":1}] != [{"a":2}]