JQ 值映射

4
我有一个很大的JSON文件,我想根据某种映射来转换一些值。
我拥有的数据看起来像:
[
    {"id":1, "value":"yes"},
    {"id":2, "value":"no"},
    {"id":3, "value":"maybe"}
]

我想把它转化为这样的列表:

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

使用固定映射:
yes => 10
no => 0
maybe => 5

我的当前解决方案是基于一个简单的if-elif-else组合,像这样:
cat data.json| jq '.data[] | .value = (if .value == "yes" then "10" elif .value == "maybe" then "5"  else "0" end)'

但这实在太丑陋了,我希望有一种更直接的方式来表达映射关系。
谢谢你的帮助。
3个回答

5

如果想避免在命令行上指定映射,则以下两种变体可能会引起兴趣。

第一种变体可与jq 1.3、jq 1.4和jq 1.5一起使用:

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

下一个变体使用--argfile选项(自jq 1.4以来可用),如果映射对象在文件中可用,则此选项非常有用:
jq --argfile mapping mapping.jq 'map(.value |= $mapping[.])' data.json

最后,在 jq 1.5 中,还提供了基于import的其他选择(!)。

如果您的输入不是一个JSON数组,而是一组行,每行都是一个JSON对象,您是否仍然可以以某种方式使用此映射技术? - JHH

2

这里有一个解决方案,使用“内联”对象,因为映射很小:

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

可以使用|=进行缩短,如peak的解决方案所示:

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

1

既然你正在翻译字符串值,那么你应该能够使用json对象来保存映射关系。然后映射就会变得很简单。

$ jq --arg mapping '{"yes":"10","no":"0","maybe":"5"}'
    'map(.value |= ($mapping | fromjson)[.])' data.json

1
请注意,在最近的 jq 构建中,您可以使用 --argjson 代替 --arg,以便在脚本中省略 | fromjson 指令。 - user3899165

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接