解决方案可能会因使用的JsonArray 实现而异,但一般方法包括以下任务:
- 将输入的JSON字符串读入
JsonArray
- 迭代输入数组,过滤掉包含
"APP"字段且值不是"V"或"S"的值
- 按
"TID" 字段分组,解决冲突以支持"V" 值
- 添加到结果
JsonArray
如果使用javax.json.JsonArray,解决方案代码如下:
static JsonArray filterArray(String json) {
JsonReader reader = Json.createReader(new StringReader(json));
JsonArray jsonaArray = reader.readArray();
Set<String> appValues = new HashSet<>(Arrays.asList("V", "S"));
return jsonaArray.stream()
.map(JsonObject.class::cast)
.filter(jo -> appValues.contains(jo.getString("APP")))
.collect(Collectors.toMap(
jo -> jo.getString("TID"),
jo -> jo,
(v1, v2) -> Stream.of(v1, v2)
.sorted(Comparator.comparing((JsonObject job) -> job.getString("APP"))
.reversed()
)
.findFirst().get(),
LinkedHashMap::new
))
.values()
.stream()
.collect(JsonCollectors.toJsonArray());
}
这里使用javax.json-api库提供JsonCollectors
测试:
String JSON = ...; // long JSON data
System.out.println(filterArray(JSON));
输出:
[{"TID":"12P","APP":"V"},{"TID":"78L","APP":"V"},{"TID":"7MP","APP":"S"}]
使用 Jackson 库的类似解决方案:
static ArrayNode filterArrayJackson(String json) throws IOException {
Set<String> appValues = new HashSet<>(Arrays.asList("V", "S"));
ObjectMapper mapper = new ObjectMapper();
ArrayNode array = (ArrayNode) mapper.readTree(new StringReader(json));
return StreamSupport.stream(array.spliterator(), false)
.filter(node -> appValues.contains(node.get("APP").asText()))
.collect(Collectors.toMap(
node -> node.get("TID").asText(),
node -> node,
(v1, v2) -> Stream.of(v1, v2)
.sorted(Comparator.comparing((JsonNode job) -> job.get("APP").asText())
.reversed()
)
.findFirst().get(),
LinkedHashMap::new
))
.values()
.stream()
.reduce(
mapper.createArrayNode(),
ArrayNode::add,
(acc, arr) -> {acc.addAll(arr); return acc;}
);
}
可以使用自定义收集器代替Stream::reduce:
// ...
.collect(Collector.of(
mapper::createArrayNode, ArrayNode::add,
(acc, arr) -> {acc.addAll(arr); return acc;}
));