多个不同路径的JSONPath联合

时间:2019-04-03 14:39:13

标签: json jsonpath

我正在尝试构建一个单个JSONPath查询,该查询将测试两个或多个路径的存在性

让我们考虑以下示例文档:

{
          "firstName": "John",
          "lastName" : "doe",
          "age"      : 26,
          "address"  : {
            "streetAddress": "naist street",
            "city"         : "Nara",
            "postalCode"   : "630-0192"
          },
          "phoneNumbers": [
            {
              "type"  : "iPhone",
              "number": "0123-4567-8888"
            },
            {
              "type"  : "home",
              "number": "0123-4567-8910"
            }
          ]
}

到目前为止,我已经发现:

$..[firstName,lastName,type]

从整个文档中获取所有这些元素。

但是,我需要检查两条不同的路径,例如:

 $.firstName 
 $.address.city

这可以通过单个JSONPath查询完成吗?我不能写任何东西:

$.[firstName,address.city]

使用XML和XPath,我可以编写:

/person/firstname | /person/address/city

并获得所有匹配的XML元素的并集。

我可以对JSONPath做同样的事情吗?

2 个答案:

答案 0 :(得分:1)

我认为您可以在原始JSONPath中找到的最接近的位置是使用递归下降和联合,即

$..['firstName','city']

Goessner实现将返回

[
   "John",
   "Nara"
]

kubernetes JSONPath支持对union运算符的扩展,允许

[‘metadata.name’, ‘status.capacity’]

其中namecapacitymetadatastatus的成员。

JSONMatch是JSONPath的一种变体,最初基于Kubernetes JSONPath解析器,它支持完全独立路径的联合,例如

[employee[5].name, company.name, wageTiers[compensation > 10000]]

JSONMatch在go中可用,而且我相信javascript也是如此。

jsoncons C++ library v0.123.0支持完全独立的路径的JSONPath联合,其中包括

$..[firstName,address.city]

答案 1 :(得分:0)

此答案不是100%的问题答案,因为它假定为 nodejs / javascript 。因为它描述了我们如何克服JSONPath的局限性,所以我希望它可以对其他人有所帮助。


我们有类似的要求。但是,我们需要寻找数百种不同的路径并对其进行处理,而性能是一个实际问题。然后,我们用object-scan替换了JSONPath。它有更多限制,但是在需要进行数据处理时具有一些优势。

这是解决问题的方法(请注意,您可以将编译和运行部分分开,以使后续执行更具性能):

const objectScan = require('object-scan');

const data = {
  firstName: 'John',
  lastName: 'doe',
  age: 26,
  address: {
    streetAddress: 'naist street',
    city: 'Nara',
    postalCode: '630-0192'
  },
  phoneNumbers: [{
    type: 'iPhone',
    number: '0123-4567-8888'
  }, {
    type: 'home',
    number: '0123-4567-8910'
  }]
};

const r = objectScan(['firstName', 'address.city'], { rtn: 'count' })(data);

console.log(r);
// => 2