如何将嵌套Java对象扁平化为指定键路径结构?
Java对象JSON风格扁平化实现方案
当然有可行的实现方式,下面提供两种常用方案:基于Jackson库的快速实现,以及手动递归反射的自定义实现。
方案一:基于Jackson库实现
Jackson是Java生态中处理JSON的主流库,我们可以借助它的JsonNode遍历对象结构,生成符合要求的扁平化键值对:
依赖引入(Maven)
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> <!-- 使用最新稳定版即可 --> </dependency>
实现代码
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; public class JsonFlattener { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); public static Map<String, Object> flatten(Object obj) throws Exception { Map<String, Object> flatMap = new HashMap<>(); JsonNode rootNode = OBJECT_MAPPER.valueToTree(obj); flattenNode("", rootNode, flatMap); return flatMap; } private static void flattenNode(String currentPath, JsonNode node, Map<String, Object> flatMap) { if (node.isValueNode()) { if (!currentPath.isEmpty()) { flatMap.put(currentPath, node.asText()); } return; } if (node.isObject()) { Iterator<Entry<String, JsonNode>> fields = node.fields(); while (fields.hasNext()) { Entry<String, JsonNode> entry = fields.next(); String newPath = currentPath.isEmpty() ? entry.getKey() : currentPath + "." + entry.getKey(); flattenNode(newPath, entry.getValue(), flatMap); } } else if (node.isArray()) { for (int i = 0; i < node.size(); i++) { String newPath = currentPath + "[" + i + "]"; flattenNode(newPath, node.get(i), flatMap); } } } }
使用示例
public class Main { public static void main(String[] args) throws Exception { // 初始化你的嵌套Java对象实例 ParentClass parent = new ParentClass(); parent.setParentField1("parentFieldValue1"); parent.setParentField2("parentFieldValue2"); ChildClass child = new ChildClass(); child.setChildField1("childFieldValue1"); child.setChildField2("childFieldValue2"); parent.setChildClass(child); ChildListItem item1 = new ChildListItem(); item1.setStringField("stringField1"); item1.setIntegerField("integerField1"); ChildListItem item2 = new ChildListItem(); item2.setStringField("stringField2"); item2.setIntegerField("integerField2"); parent.setChildClassList(List.of(item1, item2)); Map<String, Object> result = JsonFlattener.flatten(parent); // 输出结果即为目标扁平化结构 result.forEach((k, v) -> System.out.println(k + ": " + v)); } }
方案二:手动递归反射实现
如果不想依赖第三方库,可以通过反射遍历Java对象的字段,处理嵌套对象、集合和数组:
实现代码
import java.lang.reflect.Field; import java.util.*; public class ObjectFlattener { public static Map<String, String> flatten(Object obj) throws IllegalAccessException { Map<String, String> flatMap = new HashMap<>(); flattenObject("", obj, flatMap); return flatMap; } private static void flattenObject(String currentPath, Object obj, Map<String, String> flatMap) throws IllegalAccessException { if (obj == null) { return; } Class<?> clazz = obj.getClass(); // 处理基本类型、包装类、字符串、枚举 if (clazz.isPrimitive() || clazz.isEnum() || obj instanceof String || Number.class.isAssignableFrom(clazz)) { if (!currentPath.isEmpty()) { flatMap.put(currentPath, obj.toString()); } return; } // 处理集合 if (obj instanceof Collection<?>) { Collection<?> collection = (Collection<?>) obj; int index = 0; for (Object item : collection) { String newPath = currentPath + "[" + index + "]"; flattenObject(newPath, item, flatMap); index++; } return; } // 处理数组 if (clazz.isArray()) { Object[] array = (Object[]) obj; for (int i = 0; i < array.length; i++) { String newPath = currentPath + "[" + i + "]"; flattenObject(newPath, array[i], flatMap); } return; } // 处理自定义对象 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); Object fieldValue = field.get(obj); String newPath = currentPath.isEmpty() ? field.getName() : currentPath + "." + field.getName(); flattenObject(newPath, fieldValue, flatMap); } } }
使用示例
直接调用ObjectFlattener.flatten(parent)即可得到目标扁平化结构,使用方式与方案一一致。
注意:手动反射实现需要额外处理transient字段、继承字段等边界情况,若对象结构复杂,优先推荐Jackson方案。
内容的提问来源于stack exchange,提问作者VaibS
相关产品推荐
相关产品推荐

