json-iterator / go

A high-performance 100% compatible drop-in replacement of "encoding/json"
http://jsoniter.com/migrate-from-go-std.html
MIT License
13.33k stars 1.02k forks source link

jsoniter.Marshal makes ordered maps unordered #676

Open xiaozhiliaoo opened 1 year ago

xiaozhiliaoo commented 1 year ago
func Test_jsoniterMarshal(t *testing.T) {
    m := map[string]int{"c": 3, "a": 1, "b": 2}
    keys := make([]string, 0, len(m))
    for key := range m {
        keys = append(keys, key)
    }
    sort.Strings(keys)
    fmt.Println(m) // map[a:1 b:2 c:3]
    marshal, _ := jsoniter.Marshal(m) // jsoniter "github.com/json-iterator/go" package
    fmt.Println(string(marshal)) // {"c":3,"a":1,"b":2}
}

the map is ordered by sort. but jsoniter.Marshal make the map unordered. but json.Marshal json.Marshal

func Test_jsonMarshal(t *testing.T) {
    m := map[string]int{"c": 3, "a": 1, "b": 2}
    keys := make([]string, 0, len(m))
    for key := range m {
        keys = append(keys, key)
    }
    sort.Strings(keys)
    marshal, _ := json.Marshal(m) // "encoding/json" package
    fmt.Println(string(marshal)) //{"a":1,"b":2,"c":3}
}
JusticeN commented 1 year ago

You try to marshal an umsorted map m. The result is also unsorted which is ok. May be you need to sort m first before marshalling.

...

sort.Strings(keys)
sort.Strings(m)
// marshal m
// and then do the check/ print
...
CodyDWJones commented 1 year ago

the map is ordered by sort

This was a surprise to me, but you are right: the built-in encoding/json package documentation says:

"Map values encode as JSON objects... The map keys are sorted and used as JSON object keys..."

May be you need to sort m first before marshalling.

You can't sort a map in Go. Maps have no guaranteed order. The only way to do it is to copy the key-value pairs into some other data structure.