【问题标题】:JsonPath - Extract object meeting multiple criteria?JsonPath - 提取满足多个条件的对象?
【发布时间】:2020-03-31 01:41:49
【问题描述】:

在下面给出的 Json 字符串中,我想找到 category = m 的所有元素,并且“中间”数组包含与此条件匹配的元素 - 元素的“中间”数组具有 itemType = Executable 的对象。

我想使用 jsonpath 来获取所需的对象。我更喜欢不使用 jmespath,因为它对于我的目的来说太复杂了。但是,我是 jsonpath 的新手,我无法从太琐碎或基本的在线教程中找出 json 查询。我想知道使用编程语言来获取我需要的数据是否更好。请指教。

到目前为止,我只能通过使用这个 jsonpath 查询$.[?(@.category=="m")] 提取 category = m 的元素。剩下的部分怎么做?

Json: 概述 - 每个对象都有一个“内容”对象。每个内容对象除了其他字段外,通常还有一个开始、中间和结束数组。中间数组可以在其中包含多个内容对象,依此类推。一些内容对象只有一个中间数组。我有兴趣在上述内容对象中定位项目。

请注意,这不是我必须处理的实际 json。这是一款经过 SO 消毒的仿制品。

{
  "id": "123",
  "contents": {
    "title": "B1",
    "start": [],
    "middle": [
      {
        "level": "1",
        "contents": {
          "title": "C1",
          "category": "c",
          "start": [],
          "middle": [
            {
              "level": "2",
              "contents": {
                "title": "M1",
                "category": "m",
                "start": [],
                "middle": [
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT1",
                      "middle": [
                        {
                          "itemType": "Data"
                        }
                      ]
                    }
                  },
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT2",
                      "middle": [
                        {
                          "itemType": "Executable",
                          "id": "exec1"
                        }
                      ]
                    }
                  },
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT3",
                      "middle": [
                        {
                          "itemType": "Data"
                        }
                      ]
                    }
                  }
                ],
                "end": []
              }
            },
            {
              "level": "2",
              "contents": {
                "title": "M2",
                "category": "m",
                "start": [],
                "middle": [
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT1",
                      "middle": [
                        {
                          "itemType": "Data"
                        }
                      ]
                    }
                  },
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT2",
                      "middle": [
                        {
                          "itemType": "Executable",
                          "id": "exec2"
                        }
                      ]
                    }
                  }
                ],
                "end": []
              }
            }
          ],
          "end": []
        }
      },
      {
        "level": "1",
        "contents": {
          "title": "C2",
          "category": "c",
          "start": [],
          "middle": [
            {
              "level": "2",
              "contents": {
                "title": "M1",
                "category": "m",
                "start": [],
                "middle": [
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT1",
                      "middle": [
                        {
                          "itemType": "Data"
                        }
                      ]
                    }
                  },
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT2",
                      "middle": [
                        {
                          "itemType": "Executable",
                          "id": "exec3"
                        }
                      ]
                    }
                  },
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT3",
                      "middle": [
                        {
                          "itemType": "Data"
                        }
                      ]
                    }
                  }
                ],
                "end": []
              }
            },
            {
              "level": "2",
              "contents": {
                "title": "M2",
                "category": "m",
                "start": [],
                "middle": [
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT1",
                      "middle": [
                        {
                          "itemType": "Data"
                        }
                      ]
                    }
                  },
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT2",
                      "middle": [
                        {
                          "itemType": "Executable",
                          "id": "exec4"
                        }
                      ]
                    }
                  },
                  {
                    "level": "3",
                    "contents": {
                      "title": "MAT3",
                      "middle": [
                        {
                          "itemType": "Data"
                        }
                      ]
                    }
                  }
                ],
                "end": []
              }
            }
          ],
          "end": []
        }
      }
    ],
    "end": []
  }
}

【问题讨论】:

    标签: json jsonpath nested-object


    【解决方案1】:

    上下文

    • 带有嵌套对象的json1
    • jsonpath 表达式语言
    • 在 jsonpath 和 jmespath(或其他 JSON 表达式引擎)之间进行选择

    问题

    • DeveMasterJoe2 想要从嵌套的 JSON 中提取一些值

    讨论

    • jsonpath 的实现有很多,但它们并不都支持相同的功能
    • 源 JSON 的结构和规范化将影响使用纯 jsonpath 完成此操作的难易程度
    • 在选择 JSON 表达式引擎时,必须权衡多个因素
      • 跨语言实现的一致性如何?
      • 一种语言有多少种选择?
      • 规范有多清晰?
      • 有多少示例、单元测试或教程可用?
      • 谁在支持它?

    使用 Python 和 jsonpath-ng 的示例解决方案

    • 这是一个使用 python 3.7 和 jsonpath-ng 的示例解决方案
    • 这个例子混合使用了 jsonpath 和 python 而不是纯粹的 jsonpath,因为 JSON 的嵌套很重
      • 我会把它留给其他人提供一个依赖于纯 jsonpath 的答案
    • 请注意,源 JSON 可能需要稍微清理一下
      • (例如,为什么itemType==Data元素没有附加id字段?)
      • (例如,为什么在所有contents 元素上都找不到category?)
      • (例如,如果您明确指定level,当您可以通过level 确定深度时,为什么还要用大量嵌套的对象使事情复杂化?)

    这个例子:

    ## import libraries
    import codecs
    import json
    import jsonpath_ng
    from jsonpath_ng.ext import parse
    ##;;
    
    ## init vars
    href="path/to/my/jsonfile/nested_dict.json"
    json_string   = codecs.open(href, 'rb', encoding='utf8').read()
    json_dataroot = json.loads(json_string)
    final_result  = []
    ##;;
    
    ## init jsonpath outer-query
    match         = parse('$..contents.middle[*]').find(json_dataroot)
    ##;;
    
    ## iterate through outer-query and gather subelements
    for ijj,item in enumerate(match):
      ## restrict to desired category == 'm'
      if(match[ijj].value.get('contents',{}).get('category','') == 'm'):
        ## extract out desired subelements
        json_datafrag001  = [item.get('contents',{}).get('middle',{})[0] 
                  for item in match[ijj].value.get('contents',{}).get('middle',{})
                  ]
        match001 = parse("$[?(@.itemType=='Executable')]").find(json_datafrag001)
        final_result.extend(list(match001[ikk].value for ikk,item in enumerate(match001)))
    pass
    ##;;
    
    ## show final result
    vout = json.dumps(final_result, sort_keys=True,indent=4, separators=(',', ': '))
    print(vout)
    ##;;
    

    ...产生这个结果...

    [
        {
            "id": "exec1",
            "itemType": "Executable"
        },
        {
            "id": "exec2",
            "itemType": "Executable"
        },
        {
            "id": "exec3",
            "itemType": "Executable"
        },
        {
            "id": "exec4",
            "itemType": "Executable"
        }
    ]
    

    1(又名字典、关联数组、散列)

    【讨论】:

    • 对不起,我应该早点提到这一点。这不是我必须处理的实际 json。这是一款经过 SO 消毒的仿制品。创建模仿需要一段时间和人工。所以,它不是一个完美的复制品。
    • 好的,另一个可能有帮助的方面是您打算使用的编程语言或环境。
    猜你喜欢
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多