gpt4 book ai didi

java - 使用 Jsonpath 获取列表

转载 作者:行者123 更新时间:2023-11-30 06:55:31 27 4
gpt4 key购买 nike

我正在使用 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"
]
]
}]
}]
}

现在的需求是获取一个id列表,其errorMsg包含INACTIVE。为此,我使用了如下所示的过滤器。

Filter resposneFilter = Filter.filter(Criteria.where("errorMsg").is(
"INACTIVE"));
List<Map<String, Object>> respons = JsonPath.parse(response).read(
"$.payload[*]", resposneFilter);

但作为输出,我得到了有效负载中的所有值。

是否可以得到预期的结果?

最佳答案

考虑到您提供的 JSON 并阅读 Jayway JsonPath 的文档。我找到了两个可以帮助您解决问题的解决方案。

  1. 解决方案1允许您直接访问errorMsg字段,但是当有多个公司时不适用,因为您必须手动循环
  2. 解决方案 2 允许构建特定于您的情况并且有些通用的自定义谓词。

解决方案 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。

方案二

正如文档中所解释的,我定制了谓词的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
}

我想反射(reflection)一下谓词中可怕的 if 条件,如下所示:

if 条件的左边部分 - xx

这部分过滤所有包含 errorMsg 字段的。

if(ctx.item(Map.class).containsKey("errorMsg") && yy)

if 条件的右部分 - yy

这部分确保 errorMsgINACTIVE

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);
}
}

关于java - 使用 Jsonpath 获取列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35269370/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com