【问题标题】:extract array of string values based on specific keys根据特定键提取字符串值数组
【发布时间】:2019-03-20 20:06:32
【问题描述】:

希望大家都好。

我正在努力使用 JQ 尝试使用特定键从输入 json 中选择字符串值数组以进行选择。 "key":["string1",... , "stringn"] 可以嵌入到 json 中任何深度的“某处”。我只知道数组的键值。

假设我有一些 json,其中包括键 dictionnay (dict) 和 json source (source)。在这个例子中,我想选择 "key4" 和 "key11" 数组,并将它们放入带有相应键的结果 json 中。

我的示例输入是:

 {
    "dict": ["key4", "key11"],
    "source":{
    "key0": {
        "key1": "valueA",
        "key2": 123456,
        "key3": [{
                "key4": ["anotherValue4341", "anotherValue4342"],
                "key5": [{
                    "someKey351": "someValue351"
                }, {
                    "someKey352": "someValue352"
                }],
                "key6": 999
            },
            {
                "key7": "anotherValue342",
                "key8": "anotherValue352",
                "key9": 666
            }
        ],
        "key10": {
            "key11": ["lastvalue111", "lastvalue112", "lastvalue113"]
        }
    }

}}

我对这个样本的预期输出是:

{
    "key4": ["anotherValue4341", "anotherValue4342"],
    "key11": ["lastvalue111", "lastvalue112", "lastvalue113"]
}

我正在使用 JQ 来提取请求的输出。

现在我尝试重用以前的查询来选择这样的键/值:

jq '.dict as $dict | .source | reduce paths as $p (.;getpath($p) as $v| if $v|type == "string" and $dict[$v] then setpath($p; $dict[$v]) else . end)'

但它似乎与某些值有冲突:jq: error (at :26): Cannot index array with string "valueA"

我还尝试选择包含 dict 中的键的匹配对象:

jq '.dict as $dict | .source | recurse(.[]?) | objects | select(in($dict))'

但这会导致错误“无法检查数组是否有对象键”

我希望我能清楚地解释我的需求/问题。

任何提示表示赞赏。

【问题讨论】:

    标签: json jq


    【解决方案1】:

    做一个递归函数。类似的东西

    function {
        foreach $array as $key => $value {
            if ($key == KEYYOUWANT) {
               $answer = value
               break;
           } else {
                function($value)
           }
        }
    }
    

    抱歉伪代码!

    【讨论】:

    • 感谢您的回答。抱歉,我可能不清楚,但我正在使用 JQ 来处理这个 json,我正在寻找一个 JQ 查询来完成这项工作。即使一般精神是递归查询,因为你是对的。
    【解决方案2】:

    为简单起见,我们首先假设核心任务是获取与 一个特定的键。为了说明和清楚起见,让我们相应地定义一个函数:

    # Emit a (possibly empty) stream of key-value objects 
    # corresponding to the $key specified as a string
    def getKeyValue($key):
      .. | objects | select(has($key)) | {($key): .[$key]};
    

    问题的解决方案现在很简单:

    [.dict[] as $k | getKeyValue($k)] | add
    

    变化

    这个解决方案有几个潜在的问题:

    • 输入中可能根本没有出现一个或多个感兴趣的键;

    • 一个或多个感兴趣的键可能在输入中出现不止一次;

    • 如果输入很大,那么更有效的解决方案可能更可取。

    前两个问题可以轻松解决,但具体取决于具体要求。 效率问题同样可以通过修改 getKeyValue 的 def 来轻松解决 命名参数是一个字符串数组。

    【讨论】:

    • 非常感谢拆分问题的方法。您的解决方案已经处理了丢失的关键问题。重复将是另一个要求,但现在不会发生。
    【解决方案3】:

    作为学习经验(对我们双方而言),这里有一个类似于您上一个示例的版本:

    .source as $source 
    | [ 
      .dict[] | . as $key 
      | $source | .. 
      | select(.[$key]?) 
      | { ($key): .[$key]? } 
    ] | add
    

    这开始我们将.source 捕获为$source,然后迭代.dict[],将其中的每个键别名为$key。然后它切换回$source 并对其进行递归(使用..,它是recurse(.[]?) 的较短版本。然后select 查找具有名为$key 的键的任何子对象,以及以下对象构造函数提取单个键/值对。最后add 将所有这些对象合并为一个。

    我不承诺这比其他解决方案更好或更快,但它是说明性的 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多