Go Sad Limitation : Preserving order of JSON Unmarshal and other thing that Need Order

tanut aran
2 min readApr 14, 2024

--

This is shocking to me.

The other library suffer from this too like YAML but they solved it with some method implemented

Source of story:

https://github.com/golang/go/issues/27179

Quick Demo of the Problem

We are going to unmarshal hard code simple JSON.

I assume unstructured one in this example.

package main

import (
"encoding/json"
"fmt"
)

func main() {
fmt.Println("Start")
jsonString := "[{\"code\":\"001\", \"name\":\"Manhattan\",\"country\":\"US\",\"fee\":\"200\"},{\"code\":\"002\", \"name\":\"New Jersey\",\"country\":\"US\",\"fee\":\"250\"}]"
var collections []map[string]string
err := json.Unmarshal([]byte(jsonString), &collections)
if err != nil {
fmt.Println("Invalid JSON")
fmt.Println(err)
return
}
fmt.Println(collections)

for i := 0; i < len(collections); i++ {
container := collections[i]
for key, value := range container {
fmt.Println(key, value)
}
}
}

The order we are expecting are

  1. Code
  2. Name
  3. Country
  4. Fee

But every run of the program make the different output — unstable result on the very simple program

Why? The Hash Map Data Structure

Because map or Hash Map is Key-Value store with randomly assigned when created in the memory and Go standard library is built on top of this.

Solution Hard Code the Order

Everything that you put into Golang map no matter it is request, response, body, payload, any file format, protocol etc.

MUST BE DETERMINISTIC

So that you can hard code the its order like this

package main

import (
"encoding/json"
"fmt"
)

func main() {
fmt.Println("Start")
jsonString := "[{\"code\":\"001\", \"name\":\"Manhattan\",\"country\":\"US\",\"fee\":\"200\"},{\"code\":\"002\", \"name\":\"New Jersey\",\"country\":\"US\",\"fee\":\"250\"}]" var collections []map[string]string
err := json.Unmarshal([]byte(jsonString), &collections)
if err != nil {
fmt.Println("Invalid JSON")
fmt.Println(err)
return
}
fmt.Println(collections)

headers := []string{
"code",
"name",
"country",
"fee"
}

for i := 0; i < len(collections); i++ {
container := collections[i]
for j := 0; j < len(headers); j++ {
header := headers[j]
value := container[header]
fmt.Println(header, value)
}
}
}

As long as Go lang core library match the output to map. It will always cause this problem.

Discussion on Spec

There are Google Group and people on in the internet specify that JSON spec RFC does not guarantee the order.

Okay, do you think that it’s make sense that the simple program that parse JSON and print it out cannot print it in order and always get an unpredictable output?

I know everyone know the answer. So why don’t you fix it?

--

--

tanut aran
tanut aran

Written by tanut aran

Co-founder and Coder at work !

Responses (2)