2

I would like to use JQ to modify the following JSON input:

{
  "rows": [
    {
      "fields": [
        {
          "name": "id",
          "value": "k1"
        },
        {
          "name": "val",
          "value": "2340378b211aa3d8f2d7607cbddce883b87b191d0425736641e3d308ea329718"
        },
        {
          "name": "Encoding",
          "value": "hex"
        }
      ]
    },
    {
      "fields": [
        {
          "name": "id",
          "value": "k2"
        },
        {
          "name": "val",
          "value": "2340378b211aa3d8f2d7607cbddce883b87b191d0425736641e3d308ea329718"
        },
        {
          "name": "Encoding",
          "value": "hex"
        }
      ]
    }
  ]
}

so that the "hex" value of the "value" field with name "Encoding" is modified to "oct" only for the row that contains a field with .name=="id" and .value=="k1".

How would I do that? I can select a field with .value=="k1" etc. but I don't seem to be able to find a way to "go up the tree" to update the "Encoding" field subsequently.

The input cannot be expected to have a fixed field/row order.

1 Answer 1

3

Using any/2 yields a jq filter that closely matches the description of the problem in English:

.rows |= map( if any(.fields[]; .name=="id" and .value=="k1")
              then .fields |= map(if .name == "Encoding"
                                  then .value = "oct"
                                  else .
                                  end)
              else .
              end )

Using when/2

A slightly less verbose and perhaps clearer solution is possible if we use a handy general-purpose function defined as follows:

def when(filter; action): if (filter?) // null then action else . end;

We can then write simply:

.rows[] |= when( any(.fields[]; .name=="id" and .value=="k1");
                 .fields |= map( when (.name == "Encoding";
                                       .value = "oct")))

Caveats

  • You might want to check whether .value == "hex" before changing it to "oct".
  • The above filters could potentially change more than one name/value pair per "row".
Sign up to request clarification or add additional context in comments.

1 Comment

I had a related problem: Selectively update a property in a nested array, using a parent property in the value generation. This answer helped in the right direction, so I refer to it here where I answer my own question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.