【问题标题】:Using jq to produce one line of output per array element in a json object that also includes other fields from the json object使用 jq 为 json 对象中的每个数组元素生成一行输出,该对象还包括 json 对象中的其他字段
【发布时间】:2020-09-26 02:11:06
【问题描述】:

我正在尝试格式化一些由 json 对象组成的数据,其中包括一些识别信息以及一个或多个 json 对象的数组,我希望结果是每个数组元素的一行数据,每行应该包括数组元素中的一些字段和识别信息中的一些字段。

我的示例数据如下:

{
  "eventCreation": {
    "timeStamp": "2020-06-06T15:07:20Z",
    "epoch": 1591456040
  },
  "eventData": {
    "applName": "SampleApp",
    "channelName": "SYSTEM.DEF.SVRCONN",
    "connectionName": "127.0.0.1",
    "channelType": "Svrconn",
    "remoteProduct": "MQJM",
    "remoteVersion": "09010005",
    "activityTrace": [
      {
        "operationId": "Get",
        "operationTime": "11:07:18",
        "qmgrOpDuration": 102,
        "reasonCode": {
          "name": "No Msg Available",
          "value": 2033
        },
        "objectName": "SYSTEM.DEFAULT.LOCAL.QUEUE"
      },
      {
        "operationId": "Cb",
        "operationTime": "11:07:18",
        "qmgrOpDuration": 10,
        "reasonCode": {
          "name": "None",
          "value": 0
        },
        "objectName": "SYSTEM.DEFAULT.LOCAL.QUEUE"
      },
      {
        "operationId": "Cb",
        "operationTime": "11:07:18",
        "qmgrOpDuration": 12,
        "reasonCode": {
          "name": "None",
          "value": 0
        },
        "objectName": "SYSTEM.DEFAULT.LOCAL.QUEUE"
      }
    ]
  }
}

我想得到这样的输出:

"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","11:07:18","Get",102,"SYSTEM.DEFAULT.LOCAL.QUEUE",2033
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","11:07:18","Cb",10,"SYSTEM.DEFAULT.LOCAL.QUEUE",0
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","11:07:18","Cb",12,"SYSTEM.DEFAULT.LOCAL.QUEUE",0

我可以选择数组中的任何一个元素并让它打印 3 行,但如果我添加第二个元素,它将打印 9 行,第三个元素打印 27,等等。

例如:

jq -r '{channelName: .eventData.channelName, channelType: .eventData.channelType, connectionName: .eventData.connectionName, applName: .eventData.applName, remoteProduct: .eventData.remoteProduct, remoteVersion: .eventData.remoteVersion, operationId: .eventData.activityTrace[].operationId}|[.[]]|@csv' TEST.json

会产生这个:

"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get"
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb"
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb"

如果我像这样添加第二个:

jq -r '{channelName: .eventData.channelName, channelType: .eventData.channelType, connectionName: .eventData.connectionName, applName: .eventData.applName, remoteProduct: .eventData.remoteProduct, remoteVersion: .eventData.remoteVersion, operationId: .eventData.activityTrace[].operationId, qmgrOpDuration: .eventData.activityTrace[].qmgrOpDuration}|[.[]]|@csv' TEST.json

会产生这个:

"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",102
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",10
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",12
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",102
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",10
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",12
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",102
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",10
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",12

【问题讨论】:

    标签: arrays json export-to-csv ibm-mq jq


    【解决方案1】:

    使用您的方法,以下是一个解决方案:

    .eventData
    | ({channelName, channelType, connectionName, applName, remoteProduct, remoteVersion}
       + ( .activityTrace[]
           | { operationTime, operationId, qmgrOpDuration, objectName, v: .reasonCode.value}))
    | [.[]]
    | @csv
    

    关键是只迭代一次。

    另请注意,此解决方案部分通过使用 {foo: .foo} 可以缩写为 {foo} 这一事实来实现其简洁性。

    一种更有效的方法

    .eventData
    | [.channelName, .channelType, .connectionName, .applName, .remoteProduct, .remoteVersion]
      + ( .activityTrace[]
          | [.operationTime, .operationId, .qmgrOpDuration, .objectName, .reasonCode.value] )
    | @csv
    

    .operationTime 优先

    .eventData
    | [.channelName, .channelType, .connectionName, .applName, .remoteProduct, .remoteVersion] as $x
    | ( .activityTrace[] 
        | [.operationTime]
          + $x
          + [.operationId, .qmgrOpDuration, .objectName, .reasonCode.value] )
    | @csv
    
    

    【讨论】:

    • 感谢您的快速回答。你有什么其他方法可以推荐吗?有没有办法让operationTime 输出在数组的开头而不需要第二次重新排列?
    • 再次感谢您。有没有办法在 csv 输出开始时输出 operationTime 而不用第二次管道来重新排列对象中值的顺序?
    • 请参阅.operationTime first 部分。
    • 我的意思是像这样输出"11:07:18","SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",102,"SYSTEM.DEFAULT.LOCAL.QUEUE",2033
    • 这就是 $x 解决方案的作用。
    猜你喜欢
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    相关资源
    最近更新 更多