【发布时间】:2017-07-10 18:18:46
【问题描述】:
我有一个关于Flatten a JSON string to Map using Gson or Jackson 的增强问题。
我的场景包括重复键,所以上述问题中的解决方案会导致一些重复键被覆盖。所以我正在考虑通过将每个级别的键组合在一起来构造键。
那么如何实现呢?
例如:
{
"id" : "123",
"name" : "Tom",
"class" : {
"subject" : "Math",
"teacher" : "Jack"
}
}
我要获取地图:
"id" : "123",
"name" : "Tom",
"class.subject" : "Math",
"class.teacher" : "Jack"
************************更新解决方案********************* ******************
根据@Manos Nikolaidis 的回答,我可以通过考虑 ArrayNode 来实现以下解决方案。
public void processJsonString(String jsonString) throws Exception {
ObjectMapper mapper = new ObjectMapper();
ArrayNode arrayNode = (ArrayNode) mapper.readTree(jsonString);
processArrayNode(arrayNode);
}
private void processObjectNode(JsonNode jsonNode) {
Map<String, String> result = new HashMap<>();
Iterator<Map.Entry<String, JsonNode>> iterator = jsonNode.fields();
iterator.forEachRemaining(node -> mapAppender(result, node, new ArrayList<String>()));
}
private void processArrayNode(ArrayNode arrayNode) {
for (JsonNode jsonNode : arrayNode) {
processObjectNode(jsonNode);
}
}
private void mapAppender(Map<String, String> result, Map.Entry<String, JsonNode> node, List<String> names) {
names.add(node.getKey());
if (node.getValue().isTextual()) {
String name = names.stream().collect(Collectors.joining("."));
result.put(name, node.getValue().asText());
} else if (node.getValue().isArray()) {
processArrayNode((ArrayNode) node.getValue());
} else if (node.getValue().isNull()) {
String name = names.stream().collect(Collectors.joining("."));
result.put(name, null);
} else {
node.getValue().fields()
.forEachRemaining(nested -> mapAppender(result, nested, new ArrayList<>(names)));
}
}
【问题讨论】:
-
我认为您可能必须自己简单地递归(或迭代)进行转换。
-
实际上我发现了另一个能够迭代 json 字符串并正确打印值的问题。但是如何添加/保存密钥?我无法弄清楚。你能帮忙吗? stackoverflow.com/questions/22111857/…