JQ:如何使用JQ拾取的数据创建JSON对象?

JQ:如何使用JQ拾取的数据创建JSON对象?,json,jq,Json,Jq,我有一个复杂的JSON文件,其中包含数百个“属性”,其类型由“objectTypeAttributeId”标识 我知道objectTypeAttributeId=328表示tickedid,objectTypeAttributeId=329包含主机名数组等 该文件有简化版本: { "objectEntries": [ { "attributes": [ { "id": 279792, "objectTypeAttri

我有一个复杂的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”值)创建输出JSON,格式如下:

{
    "tickets": [
        {
            "ticketid": "ITSM-24210",
            "hostnames": ["testhost1", "testhost2"],
            "date": "28.02.2020 11:45"
        }
    ]
}
我是jq新手,在XSLT中,它可以使用静态模板和占位符来解决

我已经尝试过这种方法,有我的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"
}
我随后的所有尝试都是在坏掉的jq过滤器或不返回任何内容的过滤器中格式化输出更好的结果


请告诉我如何解决这个问题?

我们开始吧,它并不漂亮,可能有更好的解决方案,但它很有效:

这里有很多拆包和重新包装的工作,这会分散核心的注意力。您有一个票证数组(又名条目),我们在上面映射这些票证。我们必须从数组的不同条目中获取各种属性,这是使用reduce完成的。Reduce遍历对象数组并选择正确的对象并跟踪值

也许有一个很好的方法,但它已经起作用了,所以你可以进一步使用它,尝试简化

您的原始解决方案几乎可以工作,您在那里做得很好,只需要一张地图:

.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]}
试试看,它甚至可以与多张票一起使用;)

假设要为每个对象条目生成票据:

{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
]}

如果您将问题简化为要点(例如,似乎没有使用位置),这样会很有帮助,从而使问题更容易理解并与其他问题更相关。有效的一点是,我编辑了示例JSON,并重新删除了Redundantn属性。ID也是多余的,您可以将属性名称缩短为a、b、c等,从而节省大量空间和键入。下一次!您最初的尝试只起作用,基本上只需要添加一个地图。也许你想看看哪里出了问题。伟大的这是最好、最优雅的解决方案。非常感谢你们所有人!
{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
]}