2

When I pretty print a json file using

cat xx.json | jq .

, it prints every field in its own line. This causes extremely long output if, e.g., the json file contains arrays of x y coordinates.

Is there a way to use jq to print each level-one field (i.e. direct child of the root) of the json object in its own line?

More generally, is there a way to expand the json object up to level k, so that each level k child is printed in one line that contains its descendants (with levels greater than k).

-- Clarification:

A small illustrative example is:

echo '{"type":"MultiPolygon","coordinates":[[[[-94.9065,38.9884],[-94.8682,39.0596],[-94.6053,39.0432],[-94.6108,38.8460],[-94.6108,38.7365],[-94.9668,38.7365],[-95.0544,38.7365],[-95.0544,38.9829]]]]}"' | jq .

generates:

{
  "type": "MultiPolygon",
  "coordinates": [
    [
      [
        [
          -94.9065,
          38.9884
        ],
        [
          -94.8682,
          39.0596
        ],
        [
          -94.6053,
          39.0432
        ],
        [
          -94.6108,
          38.846
        ],
        [
          -94.6108,
          38.7365
        ],
        [
          -94.9668,
          38.7365
        ],
        [
          -95.0544,
          38.7365
        ],
        [
          -95.0544,
          38.9829
        ]
      ]
    ]
  ]
}

I'd like to print all of the value of "coordinates" and the value of each of its sibling in one line (and more generally, I'd like to achieve the same if the coordinates field is at level k of the root, instead of level 1).

3
  • Could you share an example in- and output to illustrate what you mean?
    – pLumo
    Commented Jul 14, 2022 at 19:05
  • @pLumo sure, please see the edits.
    – tinlyx
    Commented Jul 14, 2022 at 20:05
  • Is this just for visualization purposes? Wouldn't it be better to pipe your output to your favorite editor and take advantage of folds (e.g. in vim, foldmethod=indent and foldlevel)
    – r_31415
    Commented Jul 14, 2022 at 22:11

1 Answer 1

4

The jq utility does not provide this level of control over its pretty-printing. The easiest hack that you could probably do with jq is to output parts of the structure serialized:

$ jq '.coordinates[][] |= map(@json)' file
{
  "type": "MultiPolygon",
  "coordinates": [
    [
      [
        "[-94.9065,38.9884]",
        "[-94.8682,39.0596]",
        "[-94.6053,39.0432]",
        "[-94.6108,38.846]",
        "[-94.6108,38.7365]",
        "[-94.9668,38.7365]",
        "[-95.0544,38.7365]",
        "[-95.0544,38.9829]"
      ]
    ]
  ]
}

This replaces the arrays in the .coordinates[][] array with JSON encoded strings representing the serialized arrays. This would no longer be used for processing without first passing the serialized arrays through fromjson in jq. However, if the output is only for visualization, it may be a good enough solution.

Applying the serialization one level higher:

$ jq '.coordinates[] |= map(@json)' file
{
  "type": "MultiPolygon",
  "coordinates": [
    [
      "[[-94.9065,38.9884],[-94.8682,39.0596],[-94.6053,39.0432],[-94.6108,38.846],[-94.6108,38.7365],[-94.9668,38.7365],[-95.0544,38.7365],[-95.0544,38.9829]]"
    ]
  ]
}

There is a tool called jtc, which is inspired by jq, and which provides the usual pretty-printing and compact output formats for JSON documents. It also has a "semi-compact" format where it displays the inner-most object in a compact manner:

$ jtc -tc file
{
   "coordinates": [
      [
         [
            [ -94.9065, 38.9884 ],
            [ -94.8682, 39.0596 ],
            [ -94.6053, 39.0432 ],
            [ -94.6108, 38.846 ],
            [ -94.6108, 38.7365 ],
            [ -94.9668, 38.7365 ],
            [ -95.0544, 38.7365 ],
            [ -95.0544, 38.9829 ]
         ]
      ]
   ],
   "type": "MultiPolygon"
}

I'm not very familiar with jtc so I can't immediately say whether this output format is configurable (a quick glance at the user guide suggests that it's not configurable in exactly the way that you want). Note also that jtc will sort your objects by the keys.


You may also be interested in jless if your aim is to explore or view the data manually in a terminal. It would show you your data like this by default:

▼ {type: "MultiPolygon", coordinates: […]}
    type: "MultiPolygon"
  ▽ coordinates: [[[[…], […], […], […], […], […], […], […]]]]
    ▽ [0]: [[[…], […], […], […], […], […], […], […]]]
      ▽ [0]: [[…], […], […], […], […], […], […], […]]
        ▽ [0]: [-94.9065, 38.9884]
            [0]: -94.9065
            [1]: 38.9884
        ▽ [1]: [-94.8682, 39.0596]
            [0]: -94.8682
            [1]: 39.0596
        ▽ [2]: [-94.6053, 39.0432]
            [0]: -94.6053
            [1]: 39.0432
        ▽ [3]: [-94.6108, 38.846]
            [0]: -94.6108
            [1]: 38.846
        ▽ [4]: [-94.6108, 38.7365]
            [0]: -94.6108
            [1]: 38.7365
        ▽ [5]: [-94.9668, 38.7365]
            [0]: -94.9668
            [1]: 38.7365
        ▽ [6]: [-95.0544, 38.7365]
            [0]: -95.0544
            [1]: 38.7365
        ▽ [7]: [-95.0544, 38.9829]
            [0]: -95.0544
            [1]: 38.9829

... where each section is easily collapsable using the arrow keys.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .