展平JSON字符串以使用Gson或Jackson将包含每个级别键值的键设置为Map

我有一个关于使用Gson或Jackson将JSON字符串Flatten到Map的增强问题。

我的方案包括重复的密钥,因此上述问题中的解决方案将导致一些重复的密钥被覆盖。 所以我想通过将每个级别的键组合在一起来构造键。

那么如何实现呢?

例如:

{ "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 result = new HashMap(); Iterator<Map.Entry> iterator = jsonNode.fields(); iterator.forEachRemaining(node -> mapAppender(result, node, new ArrayList())); } private void processArrayNode(ArrayNode arrayNode) { for (JsonNode jsonNode : arrayNode) { processObjectNode(jsonNode); } } private void mapAppender(Map result, Map.Entry node, List 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作为JsonNode并递归遍历所有字段,并将键和值字段添加到Map。 当值是对象而不是字符串时,您可以将字段名称添加到List,以便在最终遇到字符串时加入句点。 首先创建(为了可读性)一个单独的方法,将Json字段添加到Map

 void mapAppender(Map result, Entry node, List names) { names.add(node.getKey()); if (node.getValue().isTextual()) { String name = names.stream().collect(joining(".")); result.put(name, node.getValue().asText()); } else { node.getValue().fields() .forEachRemaining(nested -> mapAppender(result, nested, new ArrayList<>(names))); } } 

并像这样使用它:

 ObjectMapper mapper = new ObjectMapper(); Map result = new HashMap<>(); mapper.readTree(json).fields() .forEachRemaining(node -> mapAppender(result, node, new ArrayList())); 

fields()返回Iterator 。 注意StackOverflowErrors以及深度嵌套JSON的低性能。

我使用下面的简单代码解决了这个问题,只考虑需要下载jettison和flattener.JsonFlattener库

 import java.util.Map; import org.codehaus.jettison.json.JSONObject; import com.github.wnameless.json.flattener.JsonFlattener; public class test { public static void main(String[] args) { String jsonString = "{\"id\" : \"123\",\"name\" : \"Tom\",\"class\" : {\"subject\" : \"Math\",\"teacher\" : \"Jack\"}}"; JSONObject jsonObject = new JSONObject(); String flattenedJson = JsonFlattener.flatten(jsonString); Map flattenedJsonMap = JsonFlattener.flattenAsMap(jsonString); System.out.println(flattenedJsonMap); } } 

参考链接: https : //github.com/wnameless/json-flattener