0

I'd like to use jq to format the output of some known keys in my objects more succinctly.

Sample object:

// test.json
[
  {
    "target": "some-string",
    "datapoints": [
      [
        123,
        456
      ],
      [
        789,
        101112
      ]
    ]
  }
]

I'd like to use JQ (with some incantation) to change this to put all the datapoints objects on a single line. E.g.

[
  {
    "target": "some-string",
    "datapoints": [[ 123, 456 ], [ 789, 101112 ]]
  }
]

I don't really know if JQ allows this. I searched around - and found custom formatters like https://www.npmjs.com/package/perfect-json which seem to do what I want. I'd prefer to have a portable incantation for this using jq alone (and/or with standard *nix tools).

4
  • 1
    jq does not provide a custom formatter option to format specific fields inside a JSON record. You could format the whole JSON with -c, but not one field alone. What you ask isn't feasible Commented Feb 12, 2023 at 16:11
  • You could turn the .datapoints array into a string containing a JSON-encoded version of the original array. That will come out as one line but beware that because of the type change it will be a different document (in contrast to both of your documents which are structurally identical): jq 'map(.datapoints |= tojson)' test.json Commented Feb 12, 2023 at 16:16
  • Not possible with jq. Not sure if this justifies a full answer. Commented Feb 12, 2023 at 17:07
  • Thanks for the responses folks. I got what I need from the answers below. Commented Feb 13, 2023 at 2:27

2 Answers 2

2

Use a two-pass approach. In the first, stringify the field using special markers so that in the second pass, they can be removed.

Depending on your level of paranoia, this second pass could be very simple or quite complex. On the simple end of the spectrum, choose markers that simply will not occur elsewhere, perhaps "<q>…</q>", or using some combination of non-ASCII characters. On the complex end of the spectrum, only remove the markers if they occur in the fields in which they are known to be markers.

Both passes could be accomplished with jq, along the lines of:

jq '.[].datapoints |= "<q>\(tojson)</q>"' |
jq -Rr 'sub("<q>(?<s>.*)</q>"; .s)'
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I appreciate the detailed explanation of the intuition.
0

Using jq and perl :

jq 'map(.datapoints |= "\u001b\(tojson)\u001b")
' test.json |  perl -pe 's/"\\u001b(.*?)\\u001b"/$1/g'

Comments

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.