使用jq获取数组中每个值及其父级。

8
我有一个类似下面的json。我想要得到每个计时器记录的输出,但包括服务名称。
{  
   "services":{  
      "service":[  
         {  
            "name":"Test Value",
            "timer":[  
               { "datetime":"08/30/2017 16:33:35", "value":"625" },
               { "datetime":"08/30/2017 16:22:38", "value":"240" }
            ]
         },
         {
            "name":"Test Value 2",
            "timer":[
               { "datetime":"08/30/2017 16:07:38", "value":"432" },
               { "datetime":"08/30/2017 15:59:07", "value":"1355" }
            ]
         }
      ]
   }
}

我想到了.services.service[].name as $name | .services.service[].timer | map([ $name, .datetime, .value ]),这可以让我得到:
[["Test Value","08/30/2017 16:33:35","625"],["Test Value","08/30/2017 16:22:38","240"]]
[["Test Value","08/30/2017 16:07:38","432"],["Test Value","08/30/2017 15:59:07","1355"]]
[["Test Value 2","08/30/2017 16:33:35","625"],["Test Value 2","08/30/2017 16:22:38","240"]]
[["Test Value 2","08/30/2017 16:07:38","432"],["Test Value 2","08/30/2017 15:59:07","1355"]]

我期望得到的输出将是:
[["Test Value","08/30/2017 16:33:35","625"],["Test Value","08/30/2017 16:22:38","240"]]
[["Test Value 2","08/30/2017 16:07:38","432"],["Test Value 2","08/30/2017 15:59:07","1355"]]

但请注意,这些值对于服务和计时器集都是重复的。我错过了什么吗?
3个回答

7

.services.service[]|[{name, timer:.timer[]}|[.name,.timer[]]]将为您提供预期输出。

.services.service[]|{name,timer:.timer[]}|[.name,.timer[]](没有数组聚合)会为每个计时器提供一个结果:

["Test Value","08/30/2017 16:33:35","625"]
["Test Value","08/30/2017 16:22:38","240"]
["Test Value 2","08/30/2017 16:07:38","432"]
["Test Value 2","08/30/2017 15:59:07","1355"]

你在尝试中省略的内容是:
引用块中的表达式"exp as $x | ..."的意思是:对于表达式"exp"的每个值,使用原始输入运行管道的其余部分,并将"$x"设置为该值。因此,“as”函数在某种程度上充当了一个foreach循环。
如果你真的想使用变量,你需要这样做:.services.service[]| .name as $name | .timer | map([ $name, .datetime, .value ])

3

这里是另一种展示数组构造函数变化的解决方案。请注意,每个数组构造函数中 [ ] 的位置略有不同。使用您的数据,此筛选器

 .services.service[] | {name} + .timer[]

生成一个对象流。
{"name":"Test Value","datetime":"08/30/2017 16:33:35","value":"625"}
{"name":"Test Value","datetime":"08/30/2017 16:22:38","value":"240"}
{"name":"Test Value 2","datetime":"08/30/2017 16:07:38","value":"432"}
{"name":"Test Value 2","datetime":"08/30/2017 15:59:07","value":"1355"}

这个过滤器。
 .services.service[] | [ {name} + .timer[] ]

生成每个服务的对象数组。
[{"name":"Test Value","datetime":"08/30/2017 16:33:35","value":"625"},{"name":"Test Value","datetime":"08/30/2017 16:22:38","value":"240"}]
[{"name":"Test Value 2","datetime":"08/30/2017 16:07:38","value":"432"},{"name":"Test Value 2","datetime":"08/30/2017 15:59:07","value":"1355"}]

这个过滤器

 .services.service[] | {name} + .timer[] | [.[]]

生成一连串的数组。
["Test Value","08/30/2017 16:33:35","625"]
["Test Value","08/30/2017 16:22:38","240"]
["Test Value 2","08/30/2017 16:07:38","432"]
["Test Value 2","08/30/2017 15:59:07","1355"]

还有这个过滤器

 .services.service[] | [ {name} + .timer[] | [.[]] ]

为每个服务生成数组的数组

[["Test Value","08/30/2017 16:33:35","625"],["Test Value","08/30/2017 16:22:38","240"]]
[["Test Value 2","08/30/2017 16:07:38","432"],["Test Value 2","08/30/2017 15:59:07","1355"]]

1
我认为将数据的层级和结果所在的位置可视化会很有帮助。在展开数据的层次结构时,我发现将其视为获取一个层级中的值并将其与下一个层级中的值组合更容易理解。
因此,在查看单个服务对象时,您需要取其名称,并将其与计时器对象的属性组合,以生成每个组合的结果。所以从这里开始:
[.name] + (properties of the timer objects)

然后您需要生成计时器对象的属性。
.timer[] | [.datetime, .value]

你可以这样理解:"对于 timer 数组中的每个项目,创建一个由 datetimevalue 属性组成的数组。"
一旦你将所有内容放在同一级别上,如果需要,你可以重新排列值,但幸运的是,在我们的情况下,所有内容都在我们想要的位置。
综合起来,这个表达式产生了名称、日期和值的单独数组,但你希望将它们收集到一个数组中。所以把它们放进去。
[[.name] + (.timer[] | [.datetime, .value])]

当你将所有内容组合在一起,就会得到结果。

.services.service[] | [[.name] + (.timer[] | [.datetime, .value])]

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