J. Groesser
J. Groesser

Reputation: 3027

How do I select multiple fields in jq?

My input file is newline delimited JSON (ndjson) looking something like this:

{
  "login": "dmaxfield",
  "id": 7449977,
  ...
}
{
  "login": "dmaxfield",
  "id": 7449977,
  ...
}

I can get all the login names with this : cat members | jq '.[].login' but I have not been able to crack the syntax to get both the login and id?

Upvotes: 296

Views: 313928

Answers (5)

nekketsuuu
nekketsuuu

Reputation: 2067

For jq >= v1.7

The builtin function pick is useful to slice objects (i.e. projection).

$ cat example.ndjson | jq -c 'pick(.login, .id)'
{"login":"dmaxfield","id":7449977}
{"login":"eiffel","id":7449978}

Nested objects can be handled nicely, too.

$ cat example.ndjson | jq -c 'pick(.login, .id, .nested.obj)'
{"login":"dmaxfield","id":7449977,"nested":{"obj":1.23}}
{"login":"eiffel","id":7449978,"nested":{"obj":4.56}}

If your input is formatted as JSON instead of NDJSON, prepend the script with .[].

$ cat example.json | jq '.[] | pick(.login, .id)' | jq -s '.'   
[
  {
    "login": "dmaxfield",
    "id": 7449977
  },
  {
    "login": "eiffel",
    "id": 7449978
  }
]

For jq < v1.7

Use { login, id }, which is a shorthand for { login: .login, id: .id }.

$ cat example.ndjson | jq -c '{ login, id }'                
{"login":"dmaxfield","id":7449977}
{"login":"eiffel","id":7449978}

For nested objects, write like this:

$ cat example.ndjson | jq -c '{ login, id, nested: { obj: .nested.obj } }'
{"login":"dmaxfield","id":7449977,"nested":{"obj":1.23}}
{"login":"eiffel","id":7449978,"nested":{"obj":4.56}}

For normal JSON files:

$ cat example.json | jq '.[] | { login, id }' | jq -s '.'
[
  {
    "login": "dmaxfield",
    "id": 7449977
  },
  {
    "login": "eiffel",
    "id": 7449978
  }
]

Notes

I used the following NDJSON file and JSON file.

$ cat example.ndjson 
{ "login": "dmaxfield", "id": 7449977, "foo": true, "nested": { "obj": 1.23 } }
{ "login": "eiffel", "id": 7449978, "foo": false, "nested": { "obj": 4.56 } }
$ cat example.json 
[
  { "login": "dmaxfield", "id": 7449977, "foo": true, "nested": { "obj": 1.23 } },
  { "login": "eiffel", "id": 7449978, "foo": false, "nested": { "obj": 4.56 } }
]

Upvotes: 26

vreyespue
vreyespue

Reputation: 781

In order to select values which are indented to different levels (i.e. both first and second level), you might use the following:

echo '[{"a":{"aa":1,"ab":2},"b":3,"c":4},{"a":{"aa":5,"ab":6},"b":7,"c":8}]' \
     | jq '.[]|[.a.aa,.a.ab,.b]'

[
  1,
  2,
  3
]
[
  5,
  6,
  7
]

Upvotes: 27

WYC
WYC

Reputation: 669

Just provide one more example here (jq-1.6):

Walk through an array and select a field of an object element and a field of object in that object

echo '[{"id":1, "private_info": {"name": "Ivy", "age": 18}}, {"id":2, "private_info": {"name": "Tommy", "aga": 18}}]' | jq ".[] | {id: .id, name: .private_info.name}" -

{
  "id": 1,
  "name": "Ivy"
}
{
  "id": 2,
  "name": "Tommy"
}

Without the example data:

jq ".[] | {id, name: .private_info.name}" -

.[]: walk through an array

{id, name: .private_info.name}: take .id and .private_info.name and wrap it into an object with field name "id" and "name" respectively

Upvotes: 55

Peter V. M&#248;rch
Peter V. M&#248;rch

Reputation: 15957

This works for me:

> echo '{"a":1,"b":2,"c":3}{"a":1,"b":2,"c":3}' | jq '{a,b}'
{
  "a": 1,
  "b": 2
}
{
  "a": 1,
  "b": 2
}

Upvotes: 178

user3899165
user3899165

Reputation:

You can use jq '.[] | .login, .id' to obtain each login followed by its id.

Upvotes: 378

Related Questions