我有一个结构如下的json文件:
{
"A": [{
"B": {
"C": [{
"D": {
"applicationNumberText": {
"value": "15570075",
"electronicText": "15570075"
},
"date": "2018-10-01",
"app": "Utility"
}
}]
}
}]
}
现在,我想检索electronicText
的值。一种方法是使用类似以下的索引
jq --stream 'select(.[0][1] == "A" and .[0][2] == "B" and .[0][3] == "C") | .[1]'
,但是结构在某些情况下可能会有所不同,因此我想通过键值而不是索引来引用。我尝试了以下方法,但无法正常工作
cat file.json | jq --stream 'select(.A|.[]. B. C|.[]. D.applicationNumberText)'
所以我想在不使用索引的情况下检索electronicText
键。
Note
:我想对大型JSON文件使用stream
选项。
答案 0 :(得分:1)
如果数组的索引是固定的,则可以使用此过滤器:
jq '.A[0].B.C[0].D.applicationNumberText.electronicText' file
并提取所有electronicText
字段,可以使用以下方法:
jq '.A[].B.C[].D.applicationNumberText.electronicText' file
如果您想使用jq流方式(虽然不清楚原因),则可以使用以下方式:
jq --stream 'select(.[0]|contains(["electronicText"]))|.[1]//empty'
这将在字符串electronicText
的键路径中查找,如果找到,则获取其关联值。 //empty
将过滤掉没有值的路径数组。
答案 1 :(得分:1)
我相信您正在寻找的是:
$targetedCustomer = Customer::on($this->connection)->where('fusercode', $user->loginname)->first();
if($targetedCustomer->agent_code != $user->agent)
{
$targetedCustomer->agent_code = $user->agent;
$targetedCustomer->save();
$logs = CustomerAgentCodeUpdateLog::on($this->connection);
$logs->customer_id = $targetedCustomer->customer_id;
$logs->old_agent_code = $targetedCustomer->agent_code;
$logs->new_agent_code = $user->agent;
$logs->type = 1;
$logs->save();
}
此过滤器期望. as $inputs | {} | setpath($inputs[0]; $inputs[1]) | .A[]?.B.C[]?.D.applicationNumberText.electronicText // empty
作为标志(如您的第一个示例),生成带有json部分的时间obj,根据第二个示例运行该过滤器,然后隐藏空结果。注意:This based on a example in the cookbook
让我概述一下正在发生的事情,以防万一:
The --stream
flag will make your receive your data differently。现在,您的过滤器将使用--stream
格式的数据运行多次,当解析器遍历您的json文件时,它一次接收一个节点。
我相信您在提及使用索引时会提及此情况,在这种情况下,这意味着您正在检查[<path>, <leaf-value>]
公开的path expression value
而不是 actual json数据
请比较以下内容的输出:
--streaming flag
setpath()接收这些路径,并且叶值参数将其放在其输入对象的顶部。例如
jq '.A[].B.C[].D.applicationNumberText.electronicText' file.json # outputs 15570075
jq --stream '.A[].B.C[].D.applicationNumberText.electronicText' file.json # multiple failures: cannot index array with string "A"
在我们的案例中,当解析访问每个节点时,我们正在生成以下值流:
{} | setpath(["a", 0, "b"], "leaf-value") # returns {"a":[{"b":"leaf-value"}]}
现在数据的格式类似于json文件,我们可以运行更熟悉的过滤器。
{"A":[{"B":{"C":[{"D":{"applicationNumberText":{"value":"15570075"}}}]}}]}
{"A":[{"B":{"C":[{"D":{"applicationNumberText":{"electronicText":"15570075"}}}]}}]}
{"A":[{"B":{"C":[{"D":{"applicationNumberText":{"electronicText":null}}}]}}]}
{"A":[{"B":{"C":[{"D":{"date":"2018-10-01"}}]}}]}
{"A":[{"B":{"C":[{"D":{"app":"Utility"}}]}}]}
请记住,两者之间没有空格。我们还在生成器.A[]?.B.C[]?.D.applicationNumberText.electronicText
和?
上都使用了.A[]
运算符,因为我们不确定这些字段是否始终可作为数组使用
最后一点,您可能需要考虑使用path()
构建路径数组,并在使用.C[]
jq标志时将其与.[0]
中显示的路径值进行比较>
答案 2 :(得分:1)
针对原始问题:
jq --stream '
select(length==2 and .[0][-1]=="electronicText")|.[1]
' input.json
"15570075"
如果您还需要value
,则可能需要考虑以下过滤器:
select(length==2 and .[0][-2]=="applicationNumberText")
| .[0][-1] as $last
| select($last == "electronicText" or $last == "value")
| {($last): .[1]}
使用您的示例JSON生成的
:
{"value":"15570075"}
{"electronicText":"15570075"}
构造“词典”的一种方法是将inputs
与-n命令行选项结合使用。只需将上述过滤器包装在结构中即可:
[inputs | ....] | add
在这里..代表上述过滤器;并使用-n和--stream选项的 both 调用jq。
答案 3 :(得分:0)
如果您知道感兴趣对象的名称,只需按名称搜索对象路径。
getpath(paths(objects) | select(.[-1] == "applicationNumberText"))
以流方式输入应该有助于解决效率问题。只需确定要保留的路径并截断感兴趣的路径即可。
$ jq -n --stream --arg key 'applicationNumberText' '
fromstream(inputs | truncate_stream2((.[0] | index($key) // empty) + 1))
' input.json
这只是检查路径并寻找"applicationNumberText"
键,然后将路径截断为该值,以便可以从流中重建它。
这使用了truncate_stream/1
函数的反向版本,该函数交换了我使用更直观的常用输入。
def truncate_stream2($count): .[0] |= .[$count:];