Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value map with JQ

Tags:

json

jq

I've a large JSON file where I'd like to transform some values based on some kind of mapping.

The data I have looks like:

[
    {"id":1, "value":"yes"},
    {"id":2, "value":"no"},
    {"id":3, "value":"maybe"}
]

And I'd like to transform that into a list like this:

[
    {"id":1, "value":"10"},
    {"id":2, "value":"0"},
    {"id":3, "value":"5"}
]

With the fixed mapping:

yes => 10
no => 0
maybe => 5

My current solution is based on a simple if-elif-else combination like this:

cat data.json| jq '.data[] | .value = (if .value == "yes" then "10" elif .value == "maybe" then "5"  else "0" end)'

But this is really ugly and I'd love to have a more direct way to express the mapping.

Thanks for your help

like image 716
pagid Avatar asked Oct 22 '25 06:10

pagid


2 Answers

If one wants to avoid having to specify the mapping on the command line, then the following two variants may be of interest.

The first variant can be used with jq 1.3, jq 1.4 and jq 1.5:

def mapping: {"yes":"10","no":"0","maybe":"5"};
map(.value |=  mapping[.])

The next variant uses the --argfile option (available since jq 1.4), and is of interest if the mapping object is available in a file:

jq --argfile mapping mapping.jq 'map(.value |= $mapping[.])' data.json

Finally, in jq 1.5, other alternatives based on import are also available (!).

like image 63
peak Avatar answered Oct 23 '25 22:10

peak


Here is a solution which uses an "inline" object since the mapping is small:

map(.value = {"yes":"10","no":"0","maybe":"5"}[.value])

which can be shorted with |= as in peak's solution to:

map(.value |= {"yes":"10","no":"0","maybe":"5"}[.])
like image 23
jq170727 Avatar answered Oct 23 '25 21:10

jq170727



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!