1

I have a json file input.json thus:

{
   "foo":{
       "prefix":"abc",
       "body":[1,2,3]
   },
   "bar":{
       "prefix":"def",
       "body":[4,5,6]    
   }
}

I would like to sort it by the outer object names, with "bar" coming before "foo" in alphabetical order like so:

{
   "bar":{
       "prefix":"def",
       "body":[4,5,6]    
   },
   "foo":{
       "prefix":"abc",
       "body":[1,2,3]
   }
}

to produce file output.json.

Versions of this question have been asked of Java/Javascript (here and here)

Is there a way to accomplish this using a command line tool like sed/awk or boost.json?

2
  • Objects in JS/JSON are unordered bags of key-value pairs, the property order has no inherent meaning. Why is the order important to you? Commented Feb 14, 2023 at 16:30
  • @knittl (As always, things are quite complicated.) I have VSCode snippets as json files where the trigger keywords are names of outermost objects in this file. Visual Studio IDE snippets are not json files. They are stored in a different format with the trigger keywords themselves being file names allowing one to sort by their filename in Windows explorer. I am trying to match the two sets of snippets. I am not sure there is any other way to do this but sort the json file. Commented Feb 14, 2023 at 16:35

2 Answers 2

2

Using jq, you could use the keys built-in to get the key names in sorted order and form the corresponding value object

jq 'keys[] as $k | { ($k) : .[$k] }' json

Note that jq does have a field --sort-keys option, which cannot be used here, as it internally sorts the inner level objects as well.

Sign up to request clarification or add additional context in comments.

5 Comments

This does work for me. TY! The output prints 4, 5, 6, etc., on separate lines. Is there a way to make the output exactly match the input file (in terms of total number of lines in the files) with only the specific lines of texts interchanged?
@Tryer jq does a default JSON formatting of the input, which unfortunately it doesn't allow to control for specific fields
To produce the desired output as given in the Q, you'd have to adapt this approach along the lines of: [keys[] as $k | {($k): .[$k]} ] | add
@peak yes indeed. I had to modify the suggested answer based on your correction to exactly get the output as I wanted in the OP. Your method also works perfectly. Hope Inian corrects his answer.
1

Here's a variable-free jq solution:

to_entries | sort_by(.key) | from_entries

It is also worth noting that gojq, the Go implementation of jq, currently always sorts the keys within all JSON objects.

2 Comments

Just to make sure I understand your answer -- should this be jq to_entries... instead of just to_entries... ? I had to install jq on my machine. It is not clear in your answer whether the utility itself is jq or some other utility.
@Tryer Yes, it's jq 'to_entries | sort_by(.key) | from_entries' input.json

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.