Akshay Hiremath
Akshay Hiremath

Reputation: 1105

jq modify value based on existing value of the attribute

I have an array of JSON objects,

[
  {
    "id": "100006578",
    "name": "Someone",
    "category": "frontend"
  },
  {
    "id": "100005436",
    "name": "Someone",
    "category": "backend"
  }
]

I want to replace the value of the id field based on its existing value. I want to use the existing value (100005436) of the id field and replace it with a new value (200005436) based on the existing value. Basically, I just want to replace the first character of the string in the existing value. The output should be like

[
  {
    "id": "200006578",
    "name": "Someone",
    "category": "frontend"
  },
  {
    "id": "200005436",
    "name": "Someone",
    "category": "backend"
  }
]

I tried a lot of stuff. But still struggling with jq. Nearest logical option I tried was to increment it jq '.externalId|map(.id+100000000)' fileWithJsonObject but it doesn't work because it is a string.

I'm really finding it hard to get the substitute expression that can take an existing value and only replace a particular part from it. There are many answers on stack overflow that talk about replacing the value of the key based on externally supplied value but I want to take the exiting value, modify it and replace it. The nearest I have gone till now is the following but unfortunately, it is not complete: jq '.externalId|to_entries|map(if .id then sub(*regex*; *tostring*))' fileWithJsonObject

I'm looking for a way to get to the right regex and how can I provide/use the current value of the id attribute in substitute.

Upvotes: 4

Views: 2018

Answers (3)

peak
peak

Reputation: 117017

I'm looking for a way to get to the right regex

.[].id |= sub("^."; "2")

(You could drop the "^" but it makes the intention abundantly clear.)

More generally:

.[].id |= (. as $id | sub("^."; $id[0:1] | tonumber+1 | tostring)

Upvotes: 5

peak
peak

Reputation: 117017

replace the first character of the string ...

A concise solution using map:

map(.id |= "2" + .[1:])

or more generally:

map(.id |= (.[0:1]|tonumber+1|tostring) + .[1:])

Even more concisely:

[].id |= "2" + .[1:]

etc...

Upvotes: 5

Δ O
Δ O

Reputation: 3710

Map thru the array, replace each element's "id" with a new value. In this case, convert original value's type to numeric, add 100 million and convert back to string.

In other words,

jq 'map( . + { "id": ( .id | tonumber + 100000000 ) | tostring } )'

Upvotes: 1

Related Questions