我使用Jayway JsonPath 2.1.0使用JsonPath解析JSON字符串。
JSON结构如下:
{
"status": "",
"source": "",
"processedRecords": 1,
"totalRecords": 4,
"description": "1 company(ies) added/updated, and 2 company(ies) failed",
"payload": [{
"Added/updated company(ies)": [
"COM001FILE"
]
}, {
"Failed company(ies)": [{
"id": "COM003FILE",
"index": "NA",
"errorMsg": [
[
"INVALID_LOCATION"
]
]
}, {
"id": "COM002FILE",
"index": "NA",
"errorMsg": [
[
"INACTIVE"
],
[
"INVALID_LOCATION",
"INACTIVE"
]
]
}]
}]
}
现在要求获取errorMsg
包含INACTIVE
的ID列表。为实现这一点,我使用的过滤器如下所示。
Filter resposneFilter = Filter.filter(Criteria.where("errorMsg").is(
"INACTIVE"));
List<Map<String, Object>> respons = JsonPath.parse(response).read(
"$.payload[*]", resposneFilter);
但作为输出我得到了有效载荷中的所有值。
是否有可能获得预期的结果?
答案 0 :(得分:4)
考虑您提供的JSON并阅读Jayway JsonPath的文档。我找到了两个可以帮助您解决问题的解决方案。
解决方案1 您拥有的过滤器似乎是正确的,如下所示:
Filter responseFilter = Filter.filter(Criteria.where("errorMsg").is("INACTIVE"));
查看你的JSON,有效负载可以被认为是起点,结构似乎是固定的payload
数组的第二个值是失败的公司,这就是你感兴趣的因此,我会写json路径如下:
Map<String, Object> inactiveFailedCompany =
parse(json).read("$.payload[1].['Failed company(ies)'][1]", responseFilter);
如果您注意到上述情况,我已指定payload[1]
,我认为这是您的JSON结构。我还指定了['Failed company(ies)'][1]
,即访问拥有INACTIVE
的公司。显然,你可以使用这个解决方案循环遍历['Failed company(ies)'][1]
索引并打印ID如下:
System.out.println("Company Object > " + inactiveFailedCompany.toString());
//output: Output > {id=COM002FILE, index=NA, errorMsg=[["INACTIVE"],["INVALID_LOCATION","INACTIVE"]]}
System.out.println("Company ID > " + inactiveFailedCompany.get("id"));
//output: COM002FILE
看看上面的解决方案,我觉得很糟糕,因为它不够好,所以我在文档中阅读了更多内容并遇到Roll your own predicate因此解决方案2.
解决方案2
正如文档中所解释的那样,我根据您的要求定制了谓词的apply
方法,解决方案如下:
Predicate inactiveCompaniesPredicate = new Predicate() {
@Override
public boolean apply(PredicateContext ctx) {
if(ctx.item(Map.class).containsKey("errorMsg") &&
((JSONArray)((JSONArray) ctx.item(Map.class).get("errorMsg")).get(0)).get(0).equals("INACTIVE")) {
return true;
} else {
return false;
}
}
};
现在使用上面的谓词如下:
List<Map<String, Object>> failedCompanies =
parse(json).read("$.payload[1].['Failed company(ies)'][?]", List.class, inactiveCompaniesPredicate);
然后循环浏览公司列表并打印失败公司的ID,如下所示:
for(Map<String, Object> object: failedCompanies) {
System.out.println(object.get("id"));
//output: COM002FILE
}
我想反思谓词中的可怕if条件如下:
if条件的左侧部分 - xx
此部分过滤所有包含errorMsg字段的内容。
if(ctx.item(Map.class).containsKey("errorMsg") && yy)
if条件的正确部分 - yy
此部分确保errorMsg
为INACTIVE
if(xx & ((JSONArray)((JSONArray) ctx.item(Map.class).get("errorMsg")).get(0)).get(0).equals("INACTIVE"))
以下是我用来测试的示例代码(我将Jsonpath 2.1及其依赖项作为外部jar导入到我的eclipse中)
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import net.minidev.json.JSONArray;
import com.jayway.jsonpath.Predicate;
import static com.jayway.jsonpath.JsonPath.parse;
public class JaywayJSON {
public static void main(String[] args) throws IOException {
String json = readFile("C:\\test_stackoverflow\\jayway.json",
Charset.defaultCharset());
/*
* //Solution 1
*
* Filter responseFilter =
* Filter.filter(Criteria.where("errorMsg").is("INACTIVE"));
*
* Map<String, Object> inactiveFailedCompany =
* parse(json).read("$.payload[1].['Failed company(ies)'][1]",
* responseFilter);
*
* System.out.println("Company Object > " +
* inactiveFailedCompany.toString()); //output: Output > {id=COM002FILE,
* index=NA, errorMsg=[["INACTIVE"],["INVALID_LOCATION","INACTIVE"]]}
*
* System.out.println("Company ID > " +
* inactiveFailedCompany.get("id")); //output: COM002FILE
*/
// solution 2
Predicate inactiveCompaniesPredicate = new Predicate() {
@Override
public boolean apply(PredicateContext ctx) {
if (ctx.item(Map.class).containsKey("errorMsg")
&& ((JSONArray) ((JSONArray) ctx.item(Map.class).get(
"errorMsg")).get(0)).get(0).equals("INACTIVE")) {
return true;
} else {
return false;
}
}
};
List<Map<String, Object>> failedCompanies = parse(json).read(
"$.payload[1].['Failed company(ies)'][?]", List.class,
inactiveCompaniesPredicate);
for (Map<String, Object> object : failedCompanies) {
System.out.println(object.get("id"));
}
}
public static String readFile(String path, Charset encoding)
throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
}