248

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?

Cornelius Roemer
  • 3,772
  • 1
  • 24
  • 55
J. Groesser
  • 2,547
  • 3
  • 11
  • 4
  • 2
    Can you provide an example of what your expected output should look like? There are many ways in which the login/id pairs could be represented. –  Jan 17 '16 at 04:40

4 Answers4

329

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

  • 3
    The users' sample input does look like a stream of objects, but because of the sample script they provide, I'm assuming it's wrapped in an array which they omitted. –  Jan 17 '16 at 16:30
  • 1
    @SantiagoLapresta: There is no need for that assumption. `jq` works great with a sequence of objects - no need for the array wrapper. The `...` strings and the last trailing comma need removal, but I consider that to be implied. – Peter V. Mørch Jun 22 '17 at 06:05
  • `jq '.[] | .login, .id'` - this creates two output records, one for .login and one for .id. – Peter V. Mørch Jun 22 '17 at 06:06
  • 125
    Or if you only want those two fields to be displayed. `jq '.[] | {login, id}'` – Cameron Taggart Aug 05 '17 at 20:00
  • 6
    @CameronTaggart, what if I want to display `login.name`? `jq '.[] | {login.name, id}'` does seem to work, what's the proper way, please? – zyxue Oct 10 '18 at 03:44
  • @zyxue I posted a solution which would work in order to select indented fields (please see below) – vreyespue Apr 03 '19 at 11:14
  • 19
    @zyxue This works: `jq '.[] | {name: .login.name, id}'` – Alex Grounds Sep 18 '19 at 18:28
  • this doesn't work if I try to keep the output sorted by display name though, e.g. `jq ".services[] | .displayName, .serviceId" services.json | sort -f` – cryanbhu Oct 22 '20 at 07:55
149

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
}
Peter V. Mørch
  • 13,830
  • 8
  • 69
  • 103
  • 1
    This is simple and exactly does what I wanted to do: have multiple input objects/hashes and take only some values of them, while also outputting them as objects. – Smar Jan 04 '21 at 05:52
  • 2
    Now I can use this on my digital photos: `ls *jpg | xargs -n 1 exiftool -json | jq '{ SourceFile,CreateDate,CreationDate,Make,Model,DateTimeOriginal,SceneType,FileAccessDate,FileModifyDate,FileInodeChangeDate,SceneCaptureType,ModifyDate }'` – Sridhar Sarnobat May 19 '21 at 04:41
  • 7
    Notice that you don't prefix the attribute by `.`. This took me a while to realize. – Sridhar Sarnobat Jun 04 '21 at 22:26
  • Just what I needed! I wonder if there is a way to make it work with nested objects. – chutz Jun 02 '23 at 01:36
48

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

cryanbhu
  • 4,780
  • 6
  • 29
  • 47
WYC
  • 599
  • 6
  • 6
26

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
]
vreyespue
  • 731
  • 9
  • 17