JSON字符串转Map:生成层级字段路径键(如A->B->C->D1)
Map<String, List<String>> with Hierarchical Path Keys Got it, let's break down how to solve this problem. You want to take your nested JSON structure and turn it into a map where each key is a hierarchical path (like A->B->C->D1) and the value is a list of all values found at that path across all array entries.
First, a quick heads-up: your original JSON has a syntax error—Y1 and Y2 are unquoted, which isn't valid JSON. I'll assume they're string values ("Y1"/"Y2") in the examples below.
Step 1: Understand the JSON Structure
Your input JSON looks like this (fixed for validity):
{ "A": [ { "B": [ { "C": [ { "D1": "V1", "D2": "X1", "D3": "Y1", "D4": "Z1" }, { "D1": "V2", "D2": "X2", "D3": "Y2", "D4": "Z2" } ] } ] } ] }
We need to traverse every node, track the path to each leaf value, and collect all values for each unique path.
Step 2: Implementation with Jackson (Java Example)
Jackson is a popular JSON library for Java, so let's use it to build our solution.
First, add the Jackson dependency if you're using Maven:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency>
Here's the code to convert the JSON to your desired map:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class JsonPathMapConverter { private static final ObjectMapper objectMapper = new ObjectMapper(); private static final Map<String, List<String>> pathValueMap = new HashMap<>(); public static void main(String[] args) throws Exception { // Fixed JSON string with quoted Y1/Y2 String json = "{ \"A\":[ { \"B\":[ { \"C\":[ { \"D1\":\"V1\", \"D2\":\"X1\", \"D3\":\"Y1\", \"D4\":\"Z1\" }, { \"D1\":\"V2\", \"D2\":\"X2\", \"D3\":\"Y2\", \"D4\":\"Z2\" } ] } ] } ] }"; JsonNode rootNode = objectMapper.readTree(json); traverseJsonNodes(rootNode, ""); // Print the final map to verify pathValueMap.forEach((path, values) -> System.out.printf("%s -> %s%n", path, values)); } private static void traverseJsonNodes(JsonNode node, String currentPath) { if (node.isObject()) { // Iterate over all fields in the object node.fields().forEachRemaining(entry -> { String newPath = currentPath.isEmpty() ? entry.getKey() : currentPath + "->" + entry.getKey(); traverseJsonNodes(entry.getValue(), newPath); }); } else if (node.isArray()) { // Iterate over each element in the array, keep the current path node.elements().forEachRemaining(element -> traverseJsonNodes(element, currentPath)); } else if (node.isValueNode()) { // We've reached a leaf value—add it to the map String value = node.asText(); pathValueMap.computeIfAbsent(currentPath, k -> new ArrayList<>()).add(value); } } }
Step 3: How It Works
- Recursive Traversal: The
traverseJsonNodesmethod recursively walks through every node in the JSON:- For objects: It extends the current path with the object's key and continues traversing the value.
- For arrays: It processes each element in the array without changing the current path (since all array elements belong to the same parent path).
- For leaf values: It adds the value to the list corresponding to the current path in the map (initializing the list if it doesn't exist yet).
Step 4: Expected Output
When you run the code, you'll get exactly what you're looking for:
A->B->C->D1 -> [V1, V2] A->B->C->D2 -> [X1, X2] A->B->C->D3 -> [Y1, Y2] A->B->C->D4 -> [Z1, Z2]
Notes for Edge Cases
- If your JSON contains non-string values (numbers, booleans),
node.asText()will convert them to strings, which fits yourList<String>requirement. - This code handles deeply nested structures and multiple levels of arrays seamlessly—just keep traversing until we hit leaf values.
- If you prefer using Gson instead of Jackson, the logic is identical; you'd just use Gson's
JsonElementand related classes for traversal.
内容的提问来源于stack exchange,提问作者rocky

