skip to Main Content

Using jq version 1.5, I need to conditionally output some json objects (in an array) based on a value within the nested object. I’ve looked here on StackOverflow and managed to get what I want working, but I wonder if it can be simplified. Here’s my data

{
  "data": [
    {
      "name": "Rich",
      "age": 10
    },
    {
      "name": "Michael",
      "age": 11
    },
    {
      "name": "Victoria",
      "age": 8
    },
    {
      "name": "Philip",
      "age": 9
    }
  ]
}

and I need to reproduce the same structure, but only for pupils 10 or older, so the output should look like this:

{
  "data": [
    {
      "name": "Rich",
      "age": 10
    },
    {
      "name": "Michael",
      "age": 11
    }
  ]
}

I have the following code which achieves what I want:

.data | to_entries | map(select(.value.age>9)) | [.[].value] | {data: .}

but I read in the jq manual that with_entries can be used to replace to_entries -> map -> from_entries, now I’m not using from_entries, but it made me question whether I should be, and if it would mean I don’t need to manually recreate my array and object in the last two pipes.

Is this the best way to solve this type of problem?

I tried using using from_entries after my map, to see if that did what I need, but I got an error:

jq: error (at <stdin>:19): Cannot use number (0) as object key

So my understanding of how that works isn’t correct.

2

Answers


  1. .data |= map(select(.age >= 10))
    

    Will produce the same output in a more cleaner way as you can test in this online demo.


    Using the |= update assignment to update the value of .data.

    Login or Signup to reply.
  2. You already have an array, so you don’t need to convert to entries first. Simply map the array and select the required elements:

    .data |= map(select(.age >= 10))
    

    Alternatively

    .data | { data: map(select(.age >= 10)) }
    

    or

    { data: (.data | map(select(.age >= 10))) }
    

    Calling to_entries on an array will give you a new array with a key-value object, the key being the index:

    [
      {
        "key": 0,
        "value": {
          "name": "Rich",
          "age": 10
        }
      },
      ...
    ]
    

    So unless your condition needs to perform calculations on the index (say, selecting every 3rd element, or only those indices which are multiples of 5), you don’t need to_entries here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search