通过按键过滤数组,使用 jq 展平 JSON 文档

Posted

技术标签:

【中文标题】通过按键过滤数组,使用 jq 展平 JSON 文档【英文标题】:Flatten a JSON document using jq by filtering an array by keys 【发布时间】:2021-07-02 16:49:48 【问题描述】:

我有一个格式如下的 JSON:

    
  "subFields": [
    
      "id": "question_1",
      "type": "radioGroup",
      "description": "Description1",
      "title": "title1",
      "subFields": [
        
          "type": "radio",
          "label": "Yes",
          "value": 1
        ,
        
          "type": "radio",
          "label": "No",
          "value": 0
        ,
        
          "uiComponent": "SmallContent",
          "componentProps": 
            "text": "* If the answer to the above question is “Yes”, please contact the Support immediately."
          
        
      ]
    ,
    
      "uiComponent": "Spacer"
    ,
    
      "id": "question_2",
      "type": "radioGroup",
      "description": "Description2",
      "title": "Title2",
      "subFields": [
        
          "type": "radio",
          "label": "Label - Value 1",
          "value": 1
        ,
        
          "type": "radio",
          "label": "Label - Value 2",
          "value": 2
        ,
        
          "type": "radio",
          "label": "Label - Value 3",
          "value": 3
        ,
        
          "type": "radio",
          "label": "Other",
          "value": 13,
          "subFields": [
            
              "id": "question_2a",
              "type": "string",
              "condition": 
                "type": "BinaryExpression",
                "operator": "==",
                "left": 
                  "type": "Identifier",
                  "name": "question_2"
                ,
                "right": 
                  "type": "Literal",
                  "value": 13
                
              
            
          ]
        
      ]
    ,
    
      "id": "question_2_b",
      "style": 
        "marginTop": "30px"
      ,
      "type": "radioGroup",
      "description": "Description3",
      "title": "",
      "subFields": [
        
          "type": "radio",
          "label": "Label - Radio 1",
          "value": 1
        ,
        
          "type": "radio",
          "label": "Label - Radio 2",
          "value": 2
        ,
        
          "type": "radio",
          "label": "Label - Radio 3",
          "value": 3
        
      ]
    ,
    
      "uiComponent": "Spacer"
    ,
    
      "id": "question_3",
      "type": "radioGroup",
      "description": "Description3",
      "title": "Title3",
      "subFields": [
        
          "type": "radio",
          "label": "Yes",
          "value": 1
        ,
        
          "type": "radio",
          "label": "No",
          "value": 0
        
      ]
    ,
    
      "uiComponent": "Spacer"
    ,
    
      "condition": 
        "type": "BinaryExpression",
        "operator": "==",
        "left": 
          "type": "Identifier",
          "name": "signer_type"
        ,
        "right": 
          "type": "Literal",
          "value": "entity"
        
      ,
      "subFields": [
        
          "uiComponent": "Spacer"
        ,
        
          "id": "question_4",
          "type": "radioGroup",
          "description": "Description_4",
          "title": "Title_4",
          "subFields": [
            
              "type": "radio",
              "label": "Yes",
              "value": 1
            ,
            
              "type": "radio",
              "label": "No",
              "value": 0
            
          ]
        ,
        
          "uiComponent": "Spacer"
        
      ],
      "uiComponent": "Block"
    ,
    
      "uiComponent": "Spacer"
    
  ],
  "uiComponent": "Container"

我想生成以下输出:

[
    
        "id": "question_1",
        "title": "title1",
        "description": "Description1",
        "type": "radioGroup",
        "questions": "radio,Yes,1"
    ,
    
        "id": "question_1",
        "title": "title1",
        "description": "Description1",
        "type": "radioGroup",
        "questions": "radio,No,0"
    ,
    
        "id": "question_2",
        "title": "Title2",
        "description": "Description2",
        "type": "radioGroup",
        "questions": "radio,Label - Value 1,1"
    ,
    
        "id": "question_2",
        "title": "Title2",
        "description": "Description2",
        "type": "radioGroup",
        "questions": "radio,Label - Value 2,2"
    ,
    
        "id": "question_2",
        "title": "Title2",
        "description": "Description2",
        "type": "radioGroup",
        "questions": "radio,Label - Value 3,3"
    ,
    
        "id": "question_2_b",
        "title": "",
        "description": "Description3",
        "type": "radioGroup",
        "questions": "radio,Label - Value 1,1"
    ,
    
        "id": "question_2_b",
        "title": "",
        "description": "Description3",
        "type": "radioGroup",
        "questions": "radio,Label - Value 2,2"
    ,
    
        "id": "question_2_b",
        "title": "",
        "description": "Description3",
        "type": "radioGroup",
        "questions": "radio,Label - Value 3,3"
    ,
    
        "id": "question_3",
        "title": "Title3",
        "description": "Description3",
        "type": "radioGroup",
        "questions": "radio,Yes,1"
    ,
    
        "id": "question_3",
        "title": "Title3",
        "description": "Description3",
        "type": "radioGroup",
        "questions": "radio,No,0"
    
]

或替代的简化版本:

[
  "question_1",
  "title1",
  "Description1",
  "radioGroup",
  "radio,Yes,1",
  "radio,No,0"
],
[
  "question_2",
  "title2",
  "Description2",
  "radioGroup",
  "radio,Label - Value 1,1",
  "radio,Label - Value 2,2",
  "radio,Label - Value 3,3",
],
[
  "question_2_b",
  "Description3",
  "radioGroup",
  "radio,Label - Value 1,1",
  "radio,Label - Value 2,2",
  "radio,Label - Value 3,3",
],
[
  "question_3",
  "Title3",
  "Description3",
  "radioGroup",
  "radio,Yes,1",
  "radio,No,0"
]

目标是仅获取包含 id 的对象(删除 "uiComponent": "Spacer" 对象)并仅获取 subFields 与数组中的这些标签:

  "subFields": [
    
      "type": "xxxx",
      "label": "xxxx",
      "value": xxxx
    ,

我能够使用以下 JQ 模式展平 JSON 数组:

jq play 1

.subFields[] | select(has("id") and .id != null)| id: .id, type: .type, description: .description, anwers: .subFields

并生成了这个结果:


  "id": "question_1",
  "type": "radioGroup",
  "description": "Description1",
  "anwers": [
    
      "type": "radio",
      "label": "Yes",
      "value": 1
    ,
    
      "type": "radio",
      "label": "No",
      "value": 0
    ,
    
      "uiComponent": "SmallContent",
      "componentProps": 
        "text": "* If the answer to the above question is “Yes”, please contact the Support immediately."
      
    
  ]


  "id": "question_2",
  "type": "radioGroup",
  "description": "Description2",
  "anwers": [
    
      "type": "radio",
      "label": "Label - Value 1",
      "value": 1
    ,
    
      "type": "radio",
      "label": "Label - Value 2",
      "value": 2
    ,
    
      "type": "radio",
      "label": "Label - Value 3",
      "value": 3
    ,
    
      "type": "radio",
      "label": "Other",
      "value": 13,
      "subFields": [
        
          "id": "question_2a",
          "type": "string",
          "condition": 
            "type": "BinaryExpression",
            "operator": "==",
            "left": 
              "type": "Identifier",
              "name": "question_2"
            ,
            "right": 
              "type": "Literal",
              "value": 13
            
          
        
      ]
    
  ]


  "id": "question_2_b",
  "type": "radioGroup",
  "description": "Description3",
  "anwers": [
    
      "type": "radio",
      "label": "Label - Radio 1",
      "value": 1
    ,
    
      "type": "radio",
      "label": "Label - Radio 2",
      "value": 2
    ,
    
      "type": "radio",
      "label": "Label - Radio 3",
      "value": 3
    
  ]


  "id": "question_3",
  "type": "radioGroup",
  "description": "Description3",
  "anwers": [
    
      "type": "radio",
      "label": "Yes",
      "value": 1
    ,
    
      "type": "radio",
      "label": "No",
      "value": 0
    
  ]

我的问题是我不知道如何删除这些部分:


  "uiComponent": "SmallContent",
  "componentProps": 
    "text": "* If the answer to the above question is “Yes”, please contact the Support immediately."
  

  "subFields": [
    
      "id": "question_2a",
      "type": "string",
      "condition": 
        "type": "BinaryExpression",
        "operator": "==",
        "left": 
          "type": "Identifier",
          "name": "question_2"
        ,
        "right": 
          "type": "Literal",
          "value": 13
        
      
    
  ]

我只为 question_3 玩了一点这个 jq:

jq play 2

.subFields[] |  id: .id, title: .title, description: .description, type: .type, subFields: .subFields | select(has("id") and .id != null) | select(.id=="question_3") |  id: .id, title: .title, description: .description, type: .type, questions: (.subFields[]|join(","))

并产生了这个结果:


  "id": "question_3",
  "title": "Title3",
  "description": "Description3",
  "type": "radioGroup",
  "questions": "radio,Yes,1"


  "id": "question_3",
  "title": "Title3",
  "description": "Description3",
  "type": "radioGroup",
  "questions": "radio,No,0"

还有

jq play 3

.subFields[] |  id: .id, title: .title, description: .description, type: .type, subFields: .subFields | select(has("id") and .id != null) | select(.id=="question_3") |  [.id, .title, .description, .type, (.subFields[]|join(","))]

结果:

[
  "question_3",
  "Title3",
  "Description3",
  "radioGroup",
  "radio,Yes,1",
  "radio,No,0"
]

你能帮我改进我创建的那些 JQ 模式以获得预期的结果吗?

提前致谢!

【问题讨论】:

【参考方案1】:

以下产生您的第一个替代方案:

.subFields[]
| select(.id?)
|  id, title, description, type +
    (.subFields[] 
     | select(.type?) 
     | [.type,.label,.value] | join(",")
     |   questions: . )

注意两个 select() 过滤器。

此处明确指定了键名,以确保遵循您指定的顺序。

【讨论】:

以上是关于通过按键过滤数组,使用 jq 展平 JSON 文档的主要内容,如果未能解决你的问题,请参考以下文章

使用 jq 为 JSON 对象的嵌套数组中的属性展平数组

使用 Jq 展平 JSON,并在输出中使用数组索引

使用 jq 保留键名展平 JSON

如何使用 jq 展平复杂的 json 结构?

使用 JQ 展平嵌套的 Json 对象

使用 jq 展平嵌套的 JSON