我read the documentation,我无法弄清楚如何使用JsonPath执行子过滤器。这是一个例子......
鉴于以下JSON,如何检索地址为Sydney
的人员列表?
我尝试了$.people[?(@.addresses[*].city=="Sydney")]
的变体无济于事。 e.g。
$.people[?(@.addresses[*].city=="Sydney")]
$.people[?(@.addresses.city=="Sydney")]
$.people[?(@..city=="Sydney")]
{
"people": [{
"name": "George",
"addresses": [{
"city": "Sydney"
}]
},
{
"name": "Jane",
"addresses": [{
"city": "Brisbane"
}]
},
{
"name": "Fred",
"addresses": [{
"city": "Perth"
},
{
"city": "Sydney"
}
]
}
]
}
{
"people": [{
"name": "George",
"addresses": [{
"city": "Sydney"
}]
},
{
"name": "Fred",
"addresses": [{
"city": "Perth"
},
{
"city": "Sydney"
}
]
}
]
}
我正在使用以下Java库:com.jayway.jsonpath:json-path:2.2.0
我正在使用http://jsonpath.com/在浏览器中测试我的jsonpath(也许这就是问题?)。
答案 0 :(得分:2)
问题是@.addresses[*].city
是一个集合。它不是该人的任何城市,也不是该人的唯一城市。
如果您正在寻找在悉尼拥有某些地址的人,则查询应为:
"$.people[?(\"Sydney\" in @.addresses[*].city)]"
示例:
String filter = "$.people[?(\"Sydney\" in @.addresses[*].city)]";
ReadContext ctx = JsonPath.parse(json);
List<Map<String, Object>> rez = ctx.read(filter, List.class);
如果您正在寻找悉尼所有地址的人,我不知道正确的查询。可以使用Predicate,但代码非常复杂。
仅供参考:
List<Map<String, Object>> rez = JsonPath.parse(json).read(
"$.people[?]",
List.class,
new Predicate() {
@Override
public boolean apply(PredicateContext ctx) {
Map<String, Object> map = ctx.item(Map.class);
ReadContext readContext = JsonPath.parse(JSONObject.toJSONString(map));
List<String> allAddresses = readContext.read("$.addresses[*].city");
List<String> sydneyAddresses = readContext.read("$.addresses[?(@.city=='Sydney')].city");
return allAddresses.size() == sydneyAddresses.size();
}
});
答案 1 :(得分:1)
首先创建一个过滤器
String jsonData = "{
"people": [{
"name": "George",
"addresses": [{
"city": "Sydney"
}]
},
{
"name": "Jane",
"addresses": [{
"city": "Brisbane"
}]
},
{
"name": "Fred",
"addresses": [{
"city": "Perth"
},
{
"city": "Sydney"
}
]
}
]
}"
Filter expensiveFilter = Filter.filter(Criteria.where(['people'][*]['address']['city'].eq("Sydney"));
现在您可以在JsonPath中添加它
String peoples = JsonPath.parse(jsonData).read("$['people'][?]", expensiveFilter).toString();