Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

copy a value to another entry in the same element

There are plenty of examples of updating a value in a nested entry in jq, but I think I have a unique question, because the value I want to provide is already in another part of the same entry.

Given the following input:

{
  "items": [
    {
      "name": "first"
    },
    {
      "name": "second"
    }
  ]
}

I want to produce this output:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

{
  "items": [
    {
      "name": "first",
      "value": "first"
    },
    {
      "name": "second",
      "value": "second"
    }
  ]
}

In other words, I want to copy the value of .name to the value of .value for each entry in items[].

Assignment is easy enough if the value is static. jq '.items[].value |= "x"

But since the value is dynamic, I always get stuck either at the wrong context level:

$ jq '.items[].value|=.name' <<< '{"items":[{"name": "first"},{"name": "second"}]}'
{
  "items": [
    {
      "name": "first",
      "value": null
    },
    {
      "name": "second",
      "value": null
    }
  ]
}

Or with the wrong output context:

jq '.items[]|(.value=.name)' <<< '{"items":[{"name": "first"},{"name": "second"}]}'
{
  "name": "first",
  "value": "first"
}
{
  "name": "second",
  "value": "second"
}

How can I make the change within the entries, for each entry, but still output the whole thing from the top level?

>Solution :

With .items[].value |= .name, .name is a reference into the input context (the outer object in this case, thus producing null values), and with .items[] | (.value = .name), the context is right but with the pipe combinator | you give up on the previous context and can’t return to it (here, resulting in the items without the surrounding array). To keep the context, use instead the update assignment operator |= on a superordinate entity.

Either on each item of the .items array:

.items[] |= (.value = .name)

Demo

Or on the entire array using map:

.items |= map(.value = .name)

Demo

Output:

{
  "items": [
    {
      "name": "first",
      "value": "first"
    },
    {
      "name": "second",
      "value": "second"
    }
  ]
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading