jq:测试密钥是否在预定义密钥列表中

时间:2016-10-19 15:33:46

标签: 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_entries(if is_json(.key) then .value = (.value|fromjson) else . end)
'

这已经产生了所需的输出:{"a":{"x":1},"y":2}。但是,鉴于jq提供了很多内置函数,例如hasincontainsinside,检查属性名称看起来很笨拙等等。

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

编辑:这是目前的解决方案,基于峰值答案。

#!/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)
";}

1 个答案:

答案 0 :(得分:2)

有三种方法可以改进您的程序:

  1. (效率)避免创建不必要的数组(在is_json);
  2. (效率)使用“短路”语义来避免 不必要地迭代;
  3. (效率)避免与with_entries有关的构造/解构;
  4. 在大多数情况下,我认为您会同意这里提供的替代方案更简单,更简洁或更易读。

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

    def is_json($o): any( ("a","b"); . == $o );
    
    with_entries(if is_json(.key) then .value |= fromjson else . end)
    

    另请注意使用'| =',其中您使用了'='。

    如果您的jq没有any/2,那么您可以使用以下内容 定义,虽然缺少短路语义:

    def any(s): reduce s as $i (false; . == true or $i);
    

    最后,为了避免使用with_entries,您可以使用reduce并完全取消is_json

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