How to pretty print using jq, so that multiple values are on the same line?
Asked Answered
R

3

8

What I get from jq is:

{
  "frameGrid": {
    "size": [
      24,
      24
    ],
    "dimensions": [
      1,
      1
    ],
    "names": [
      [
        "default"
      ]
    ]
  }
}

What I would like to see is something more like this:

{
  "frameGrid": {
    "size": [24,24], 
    "dimensions": [1,1],
    "names": [["default"]]
  }
}

I know both forms are valid, and that jq has a compact/pretty print mode. But is there something in-between? I'm looking to somehow format a larger json file that has many more array values than this, so that it's easily readable and printable. Maybe I'm just using the wrong tool for this job?

(please excuse the horrid formating choice. Seems code-sample doesn't like json formats much)

Roxy answered 18/10, 2017 at 8:29 Comment(3)
It would take a lot of work to write the jq code for a decent pretty-printer of the type described. Your best bet would probably be to use a tool such as npmjs.com/package/json-stringify-pretty-compactMusquash
Essentially a duplicate of #42730231Underlinen
Thanks @JeffMercado. While not exactly the same goal, it does fit into the same area of PP typing. I think a combination of your info and the ones provided here may help others determine a common solution. You guys rock! I did search high and low for something of this nature before posting this question.Roxy
S
8

While it is probably best to use a tool like the one peak suggested if your json isn't too complex you could use a second jq invocation to postprocess the output of the first. For example if your data is in data.json

$ jq -M . data.json | jq -MRsr 'gsub("\n      +";"")|gsub("\n    ]";"]")'

produces

{
  "frameGrid": {
    "size": [24,24],
    "dimensions": [1,1],
    "names": [["default"]]
  }
}
Skipjack answered 18/10, 2017 at 9:22 Comment(1)
While it can't handle the bigger file structures without a lot of process time, it does work inside jq, and it doesn't seem to be breaking at all. I don't need to run these reports very often, so this solution is working great so far! While I love the awk answer, this stays true to the subject of the question. Wish I could pick both of you.Roxy
M
6

As @jq170727 mentioned, postprocessing after a pretty-printing run of jq (e.g. jq .) is worth considering. In that vein, here is an awk script that might suffice:

#!/bin/bash

awk '
  function ltrim(x) { sub(/^[ \t]*/, "", x); return x; }
  s && NF > 1 && $NF == "["  { s=s $0;               next}
  s && NF == 1 && $1 == "]," { print s "],";   s=""; next}
  s && NF == 1 && $1 == "["  { print s;        s=$0; next}
  s && NF == 1 && $1 == "{"  { print s; print; s=""; next}
  s && NF == 1 && $1 == "]"  { print s $1;     s=""; next}
  s && NF == 1 && $1 == "}"  { print s;        s=$0; next}
  s                          { s=s ltrim($0);        next}
  $NF == "["                 { s=$0;                 next}
  {print}
'

Examples

With the example input, the invocation:

 jq . example.json | ./pp

produces:

{
  "frameGrid": {
    "size": [24,24],
    "dimensions": [1,1],
    "names": [
      ["default"]
    ]
  }
}

The invocation:

jq -n '{a:[1,2,3,[1,2,3,4]],b:2,c:{d:[1,2,{e:[3,4]}]}}' | ./pp

produces:

{
  "a": [1,2,3,
    [1,2,3,4]
  ],
  "b": 2,
  "c": {
    "d": [1,2,
      {
        "e": [3,4]
      }
    ]
  }
}
Musquash answered 18/10, 2017 at 20:51 Comment(1)
Both of your guys' answers helped me a lot, and I really do thank you! I think if my datasets get any bigger, I'll move towards awk. But for now, the jq remedy is working fine.Roxy
J
2

If you're not married to jq, take a look at FracturedJson. There's a web-based formatter, a commandline app, and a couple libraries.

FracturedJson inlines arrays/objects as long as they're neither too long nor too complex (according to your settings). It can also do arrays as multiple lines with multiple items per line, again, if they're not too complex. Otherwise it breaks things out in the classic indented form.

Here's the data from the original question using the default settings:

{
    "frameGrid": {
        "size": [24, 24],
        "dimensions": [1, 1],
        "names": [ ["default"] ]
    }
}

Disclosure: I'm the author of FracturedJson. It's open source under an MIT license.

Janettajanette answered 8/11, 2020 at 3:27 Comment(2)
FracturedJson look's cool but we can not use it with pipe; $ cat some.json | compact-json we only can give some file to it ;(Hollands
Every pipeline is a file if you squint at it; you could transform to compact-json <( cat some.json ). Untested hah!Zizith

© 2022 - 2024 — McMap. All rights reserved.