select few elements of an inner array using jq

I want create a more simple json with the same original structure but with one a small sample.

As example, If I have this json:

{
    "field1": [
        {
            "a": "F1A1",
            "b": "F1B1"
        },
        {
            "a": "F1A2",
            "b": "F1B2"
        },
        {
            "a": "F1A3",
            "b": "F1B3"
        },
        {
            "a": "F1A4",
            "b": "F1B4"
        }
    ],
    "field2": [
        {
            "a": "F2A1",
            "b": "F2B1"
        },
        {
            "a": "F2A2",
            "b": "F2B2"
        }
    ],
    "field3": [
        {
            "a": "F3A1",
            "b": "F3B1"
        },
        {
            "a": "F3A2",
            "b": "F3B2"
        }
    ]

}

I want to get the first array element from the first field. So I was expecting this:

{
    "field1": [
        {
            "a": "F1A1",
            "b": "F1B1"
        }
    ],

}

I executed jq "select(.field1[0])" tmp.json but it returns the original json.

Bonus:
As bonus, how to do the same but extracting let’s say field1 and elements in the array with a=="F1A1" and a=="F1A4", so will expect?:

{
    "field1": [
        {
            "a": "F1A1",
            "b": "F1B1"
        },
        {
            "a": "F1A4",
            "b": "F1B4"
        }
    ]

}

>Solution :

reduce the oouter object to your field using {field1}, then map this field to an array containing only the first item:

jq '{field1} | map_values([first])'
{
  "field1": [
    {
      "a": "F1A1",
      "b": "F1B1"
    }
  ]
}

To filter for certain items use select:

jq '{field1} | map_values(map(select(.a == "F1A1" or .a == "F1A4")))'
{
  "field1": [
    {
      "a": "F1A1",
      "b": "F1B1"
    },
    {
      "a": "F1A4",
      "b": "F1B4"
    }
  ]
}

As you can see, select does something different. It passes on its input if the argument evaluates to true. Therefore its output is either all or nothing, never just a filtered part. (Of course, you can use select to achieve specific filtering, as shown above.)

Leave a Reply