繁体   English   中英

JQ:如何使用jq挑选的数据创建JSON object?

[英]JQ: How to create JSON object using data picked by jq?

我有一个复杂的 JSON 文件,其中包含数百个“属性”,其类型由“objectTypeAttributeId”标识。

我知道 objectTypeAttributeId=328 表示 tickedid,objectTypeAttributeId=329 包含主机名数组等。

该文件有简化版本:

{
  "objectEntries": [
    {
      "attributes": [
        {
          "id": 279792,
          "objectTypeAttributeId": 328,
          "objectAttributeValues": [
            {
              "displayValue": "ITSM-24210"
            }
          ]
        },
        {
          "id": 279795,
          "objectTypeAttributeId": 329,
          "objectAttributeValues": [
            {
              "displayValue": "testhost1"
            },
            {
              "displayValue": "testhost2"
            }
          ]
        },
        {
          "id": 279793,
          "objectTypeAttributeId": 330,
          "objectAttributeValues": [
            {
              "displayValue": "28.02.2020 11:45"
            }
          ]
        }
      ]
    }
  ]
}

我需要使用从输入 JSON 中挑选出的特定值(根据“objectTypeAttributeId”值)创建 output JSON,格式如下:

{
    "tickets": [
        {
            "ticketid": "ITSM-24210",
            "hostnames": ["testhost1", "testhost2"],
            "date": "28.02.2020 11:45"
        }
    ]
}

我是 jq 的新手,在 XSLT 中,它可以使用 static 模板和占位符来选择值来解决。

我试过这种方法,有我的 jq 过滤器:

.objectEntries[].attributes[] |
  {ticketid: select(.objectTypeAttributeId == 328) | .objectAttributeValues[0].displayValue},
  {hostnames: select(.objectTypeAttributeId == 329) | [.objectAttributeValues[].displayValue]},
  {date: select(.objectTypeAttributeId == 330) | .objectAttributeValues[0].displayValue}

但这种方法的结果是:

{
  "ticketid": "ITSM-24210"
}
{
  "hostnames": [
    "testhost1",
    "testhost2"
  ]
}
{
  "date": "28.02.2020 11:45"
}

我随后尝试格式化 output 更好地以损坏的 jq 过滤器或不返回任何内容的过滤器结束。

请任何想法如何解决这个问题?

假设要为每个 object 条目生成一张票:

{tickets: [
  .objectEntries[]
  | [.attributes[]
    | [.objectTypeAttributeId,
      (.objectAttributeValues | map(.displayValue))] as [$id, $val]
    |   if $id == 328 then {ticketId:  $val[0]}
      elif $id == 329 then {hostnames: $val}
      elif $id == 330 then {date:      $val[0]}
      else empty end
  ] | add
]}

在线演示

我们在这里 go,它不是很漂亮,可能有更好的解决方案但它有效: https://jqplay.org/s/sxussfa2Vj

.objectEntries | {tickets: map(.attributes | 
{ticketID: (reduce .[] as $r (null;  if $r.objectTypeAttributeId == 328 
then $r.objectAttributeValues[0].value else . end)),
date: (reduce .[] as $r (null;  if $r.objectTypeAttributeId == 330
then $r.objectAttributeValues[0].value else . end)), 
hostnames: (reduce .[] as $r ([];  if $r.objectTypeAttributeId == 329 
then $r.objectAttributeValues | map(.value) else . end))})}

这里有很多拆包和重新包装,有点分散了核心的注意力。 您有一组票证(也称为条目),在这些票证上我们有 map。我们必须从数组的不同条目中获取各种属性,这是使用 reduce 完成的。 Reduce 遍历对象数组并挑选出正确的对象并跟踪值。

也许有一个不错的方法,但这已经有效,因此您可以进一步尝试,尝试简化。

你原来的解决方案几乎可以工作,你在那里做得很好,只需要一个 map:

.objectEntries[].attributes | 
{ticketid: . | map(select(.objectTypeAttributeId == 328))[0] | 
.objectAttributeValues[0].displayValue, 
date: . | map(select(.objectTypeAttributeId == 330))[0] |
.objectAttributeValues[0].displayValue, 
hostnames: . | map(select(.objectTypeAttributeId == 329))[0] | 
[.objectAttributeValues[].displayValue]}

试试看,它甚至适用于多张票;) https://jqplay.org/s/ydoCgv9vsI

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM