32

In python you can produce JSON with keys in sorted order by doing

import json
print json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4, separators=(',', ': '))

I have not found a similar option in Go. Any ideas how I can achieve similar behavior in go?

sheki
  • 8,531
  • 11
  • 48
  • 69
  • can you please post the solution you used ? I tried using `NewEncoder(...).Encode(structInstance)` but the output json keys are not sorted. – coding_idiot Jun 04 '17 at 04:41

2 Answers2

76

The json package always orders keys when marshalling. Specifically:

  • Maps have their keys sorted lexicographically

  • Structs keys are marshalled in the order defined in the struct

The implementation lives here ATM:

Gustavo Niemeyer
  • 20,403
  • 5
  • 53
  • 46
  • 2
    Noice. I wonder why the encoding/json documentation doesn't mention this crucial property. – Hannes Landeholm Oct 17 '15 at 20:52
  • 5
    Now it is documented : https://golang.org/pkg/encoding/json/#Marshal : Map values encode as JSON objects. The map's key type must either be a string, an integer type, or implement encoding.TextMarshaler. The map keys are sorted and used as JSON object keys by applying the following rules, subject to the UTF-8 coercion described for string values above – programaths Apr 28 '17 at 08:24
  • 8
    What about the struct keys? Is the order documented? – updogliu Jun 08 '17 at 00:41
  • Radik provided a great answer below. To get the struct keys sorted, you either need to do use his `JsonRemarshal` function (which will incur additional time penalty), or write your own implementation of `Marshal` using reflection. – Victor K. May 16 '21 at 17:33
8

Gustavo Niemeyer gave great answer, just a small handy snippet I use to validate and reorder/normalize []byte representation of json when required

func JsonRemarshal(bytes []byte) ([]byte, error) {
    var ifce interface{}
    err := json.Unmarshal(bytes, &ifce)
    if err != nil {
        return []byte{}, err
    }
    output, err := json.Marshal(ifce)
    if err != nil {
        return []byte{}, err
    }
    return output, nil
}
Radek 'Goblin' Pieczonka
  • 19,215
  • 5
  • 45
  • 44