Json jq:测试一个键是否在预定义键列表中

Json jq:测试一个键是否在预定义键列表中,json,key,jq,any,Json,Key,Jq,Any,我有一个例子需要在JSON中解析引用的JSON。 我知道哪些可选属性将包含引用的JSON,哪些不包含。 因此,我想检查属性键是否在可能键的列表中。我已有以下资料: # attributes "a" and "b" contain quoted JSON echo '{"a":"{\"x\":1}","y":2}' | jq -c ' def is_json($o): ["a","b"] | (map(select(. == $o)) | length) > 0; with_en

我有一个例子需要在JSON中解析引用的JSON。 我知道哪些可选属性将包含引用的JSON,哪些不包含。 因此,我想检查属性键是否在可能键的列表中。我已有以下资料:

# attributes "a" and "b" contain quoted JSON
echo '{"a":"{\"x\":1}","y":2}' |
jq -c '
   def is_json($o): ["a","b"] | (map(select(. == $o)) | length) > 0;
   with_entries(if is_json(.key) then .value = (.value|fromjson) else . end)
'
这已经产生了所需的输出:
{“a”:{“x”:1},“y”:2}
。然而,鉴于
jq
提供了许多内置函数,例如
中的
包含
内部的
等,属性名称的检查看起来很笨拙

问题:是否有更好的方法检查属性键是否在给定列表中

编辑:这是基于peak答案的当前解决方案

#!/bin/bash
to_array_string() { echo "$*" | awk -v OFS='","' 'NF > 0 {$1=$1; print "\""$0"\""}'; }
to_json_array_string() { echo "["`to_array_string "$@"`"]"; }

parse_json_jq() { jq -c "
   reduce keys[] as \$key
   (.; if any((`to_array_string "$@"`); . == \$key) and .[\$key] != null then .[\$key] |= fromjson else . end)
";}

有三种方法可以改进您的计划:

  • (效率)避免创建不必要的数组(在
    is_json
    中)
  • (效率)使用“短路”语义来避免 不必要地重复
  • (效率)避免与_条目相关的构造/解构 在大多数情况下,我认为您会同意这里提供的备选方案更简单、更简洁或更可读

    如果您有jq的1.5版或更高版本,那么主要的改进 可以使用任何/2:

    def is_json($o): any( ("a","b"); . == $o );
    
    with_entries(if is_json(.key) then .value |= fromjson else . end)
    
    还请注意在使用“=”的地方使用了“|=”

    如果您的jq没有
    任何/2
    ,那么您可以使用以下命令 定义,尽管它缺乏短路语义:

    def any(s): reduce s as $i (false; . == true or $i);
    
    最后,为了避免将
    用于_条目
    ,您可以使用
    减少
    并完全消除
    是_json

    reduce keys[] as $key
      (.; if any(("a","b"); . == $key) then .[$key] |= fromjson else . end)
    

    此解决方案的Thx。我只需要添加另一个
    null
    检查即可(请参见问题的编辑)。