xpt
xpt

Reputation: 22994

jq to output results as JSON

jq is suppose to

process/filter JSON inputs and producing the filter's results as JSON

However, I found that after the jq process/filter, output result is no longer in JSON format any more.

E.g., https://stedolan.github.io/jq/tutorial/#result5, i.e.,

$ curl -s 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.[] | {message: .commit.message, name: .commit.committer.name}'
{
  "message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
  "name": "Stephen Dolan"
}
{
  "message": "Reject all overlong UTF8 sequences.",
  "name": "Stephen Dolan"
}
. . . 

Is there any workaround?

UPDATE:

How to wrap the whole return into a json structure of:

{ "Commits": [ {...}, {...}, {...} ] }

I've tried:

jq '.[] | Commits: [{message: .commit.message, name: .commit.committer.name}]'
jq 'Commits: [.[] | {message: .commit.message, name: .commit.committer.name}]'

but neither works.

Upvotes: 13

Views: 12458

Answers (3)

HeyWatchThis
HeyWatchThis

Reputation: 23463

To answer your direct question, if you are doing something like starting with json, then your jq produces a json stream ,

echo '[{"commit": {"message": "hi"}},{"commit": {"message": "okay"}},{"commit": {"message": "bye"}}]' \
    | jq '.[] | {message: .commit.message}'
{
  "message": "hi"
}
{
  "message": "okay"
}
{
  "message": "bye"
}

Then you just --slurp it , like

echo '[{"commit": {"message": "hi"}},{"commit": {"message": "okay"}},{"commit": {"message": "bye"}}]' \
    | jq '.[] | {message: .commit.message}'\
    | jq --slurp
[
  {
    "message": "hi"
  },
  {
    "message": "okay"
  },
  {
    "message": "bye"
  }
]

( NOTE @peak hinted at this , -s is short for --slurp )

Upvotes: 4

peak
peak

Reputation: 116750

Technically speaking, unless otherwise instructed (notably with the -r command-line option), jq produces a stream of JSON entities.

One way to convert an input stream of JSON entities into a JSON array containing them is to use the -s command-line option.

Response to UPDATE

To produce a JSON object of the form:

{ "Commits": [ {...}, {...}, {...} ] }

you could write something like:

jq '{Commits: [.[] | {message: .commit.message, name: .commit.committer.name}]}'

(jq understands the '{Commits: _}' shorthand.)

Upvotes: 10

xpt
xpt

Reputation: 22994

Found it, on the same page,

https://stedolan.github.io/jq/tutorial/#result6

If you want to get the output as a single array, you can tell jq to “collect” all of the answers by wrapping the filter in square brackets:

jq '[.[] | {message: .commit.message, name: .commit.committer.name}]'

Upvotes: 17

Related Questions