从Map和Struct中排序JSON中的差异

时间:2016-04-18 15:16:28

标签: json dictionary go struct marshalling

当从map[string]interface{}和等效struct编组时,返回的JSON类似但在键的内部顺序上不同:

var arg1 = map[string]interface{}{
    "foo": "bar",
    "baz": map[string]interface{}{
        "bee": "boo",
    },
}

type Arg struct {
    Foo string                 `json:"foo"`
    Baz map[string]interface{} `json:"baz"`
}

var arg2 = &Arg{
    Foo: "bar",
    Baz: map[string]interface{}{
        "bee": "boo",
    },
}

func main() {
    result1, _ := json.Marshal(arg1)
    result2, _ := json.Marshal(arg2)

    fmt.Println(reflect.DeepEqual(result1, result2)
    fmt.Println(string(result1))
    fmt.Println(string(result2))

    // false
    // {"baz":{"bee":"boo"},"foo":"bar"}
    // {"foo":"bar","baz":{"bee":"boo"}}

}

检查playground here

虽然在JSON中顺序并不重要,但我想知道为什么结果的排序方式不同?

2 个答案:

答案 0 :(得分:5)

地图中元素的顺序未定义为Go使用hash table来实现它们。您应该期望以任何顺序编组元素。

编组结构时,JSON字段的顺序应与结构中字段的顺序匹配。这是通过反射访问字段的副作用。你仍然不应该依赖这种副作用。

JSON中元素的顺序并不重要。比较JSON结构的问题与将树与无序子节点进行比较的问题相同。

答案 1 :(得分:4)

encoding / json包在sorted key order中编组映射,并按照声明字段的顺序进行结构化。

虽然没有记录encoding / json包使用的顺序,但可以安全地假设地图按照排序的键顺序编组,并且结构以字段声明顺序编组。标准库和其他地方有许多依赖于这些订单的测试。