gojq icon indicating copy to clipboard operation
gojq copied to clipboard

cli: option -k to preserve the order of keys

Open starius opened this issue 1 year ago • 0 comments

I read feedback on https://github.com/itchyny/gojq/pull/189 and https://github.com/itchyny/gojq/issues/84 and implemented it in a way that does not change gojq (the library). Also it is completely optional and it only affects encoding and decoding. Everything in between is the same. Still it covers majority of my jq uses: pretty printing, extraction by path. Maps in JSON are often Go structs and preserving the order improves readability a lot.

It builds an external map from object pointer to the list of keys as seen in the input. If an object does not change during the whole operation of gojq, cli can find the original order of keys during encoding by looking into the map and checking if the set of keys is the same. This works for both JSON and YAML.

go-ordered-map is used as an intermediate object created during decoding and encoding (in case of YAML). After parsing is done, the list of keys is extracted from orderedmap and the map is turned into a regular map[string]any. A pointer to that map is added to a global table map[uintptr][]string which stores the order of keys. When encoding, this data is used to put keys in the right order.

Example:

$ echo '{"tx": {"open": 1, "close": 2}, "accept": true}' | gojq . 
{
  "accept": true,
  "tx": {
    "close": 2,
    "open": 1
  }
}

$ echo '{"tx": {"open": 1, "close": 2}, "accept": true}' | gojq -k . 
{
  "tx": {
    "open": 1,
    "close": 2
  },
  "accept": true
}

starius avatar Jan 19 '24 17:01 starius