Java实现:将扁平化Map<String, Object>转换为嵌套对象
扁平化Map转嵌套对象实现方案
问题说明
已实现嵌套对象转扁平化Map<String, Object>的功能,现需实现反向逻辑:将扁平化Map转换回对应的嵌套对象。
示例类定义
class BaseModel implements Serializable {} class A extends BaseModel { String test; int testInt; B b; } class B extends BaseModel { Double testDouble; List<C> c; } class C extends BaseModel { float testFloat; }
目标嵌套对象JSON示例
{ "test": "t", "testInt": 1, "b": { "testDouble": 1.1, "c": [{ "testFloat": 1.2 }] } }
现有扁平化转换方法
public static Map<String, Object> getDataForProcess(BaseModel model, String fieldName) { Map<String, Object> m = new HashMap<>(); Class<?> thisClass = null; try { if (model != null) { thisClass = Class.forName(model.getClass().getName()); Field[] aClassFields = thisClass.getDeclaredFields(); for (Field f : aClassFields) { String fName = fieldName != null && !fieldName.isEmpty() ? fieldName + "_" + f.getName() : f.getName(); if (BaseModel.class.isAssignableFrom(f.getType())) { BaseModel subModel = (BaseModel) f.get(model); Map<String, Object> subMap = getDataForProcess(subModel, fName); m.putAll(subMap); } else if (List.class.isAssignableFrom(f.getType())) { @SuppressWarnings("unchecked") List<BaseModel> list = (List<BaseModel>) f.get(model); for (int i = 0; i < list.size(); i++) { Map<String, Object> listItemMap = getDataForProcess(list.get(i), fName + "_" + i); m.putAll(listItemMap); } } else { if (!fName.contains("serialVersionUID")) { m.put(fName, f.get(model)); } } } } } catch (Exception e) { e.printStackTrace(); } return m; }
扁平化Map示例
{ "test": "t", "testInt": 1, "b_testDouble": 1.1, "b_c_0_testFloat": 1.2 }
反向转换实现代码
import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; public class ModelConverter { public static <T extends BaseModel> T flatMapToNestedObject(Map<String, Object> flatMap, Class<T> targetClass) { try { T instance = targetClass.getDeclaredConstructor().newInstance(); processFlatMap(flatMap, instance, ""); return instance; } catch (Exception e) { e.printStackTrace(); return null; } } private static void processFlatMap(Map<String, Object> flatMap, BaseModel currentModel, String prefix) throws Exception { Class<?> currentClass = currentModel.getClass(); Field[] fields = currentClass.getDeclaredFields(); for (Field field : fields) { if ("serialVersionUID".equals(field.getName())) { continue; } field.setAccessible(true); String fieldKey = prefix.isEmpty() ? field.getName() : prefix + "_" + field.getName(); // 处理BaseModel类型的嵌套对象 if (BaseModel.class.isAssignableFrom(field.getType())) { BaseModel subModel = (BaseModel) field.getType().getDeclaredConstructor().newInstance(); processFlatMap(flatMap, subModel, fieldKey); // 检查是否有对应层级的字段,避免创建空对象(可按需调整) boolean hasSubFields = flatMap.keySet().stream().anyMatch(k -> k.startsWith(fieldKey + "_")); if (hasSubFields || flatMap.containsKey(fieldKey)) { field.set(currentModel, subModel); } } // 处理List类型 else if (List.class.isAssignableFrom(field.getType())) { Class<?> genericType = getListGenericType(field); if (genericType == null || !BaseModel.class.isAssignableFrom(genericType)) { continue; } // 按索引分组收集当前List下的所有字段key Map<Integer, List<String>> indexKeyMap = flatMap.keySet().stream() .filter(k -> k.startsWith(fieldKey + "_")) .map(k -> k.substring(fieldKey.length() + 1)) .filter(k -> k.matches("\\d+_.+")) .collect(Collectors.groupingBy( k -> Integer.parseInt(k.split("_")[0]), Collectors.toList() )); if (!indexKeyMap.isEmpty()) { List<BaseModel> list = new ArrayList<>(); List<Integer> sortedIndexes = new ArrayList<>(indexKeyMap.keySet()); Collections.sort(sortedIndexes); for (int index : sortedIndexes) { BaseModel listItem = (BaseModel) genericType.getDeclaredConstructor().newInstance(); String itemPrefix = fieldKey + "_" + index; processFlatMap(flatMap, listItem, itemPrefix); list.add(listItem); } field.set(currentModel, list); } } // 处理普通字段 else { if (flatMap.containsKey(fieldKey)) { Object value = flatMap.get(fieldKey); // 处理基本类型与包装类的转换 if (field.getType().isPrimitive()) { value = convertPrimitiveValue(value, field.getType()); } field.set(currentModel, value); } } } } // 获取List字段的泛型类型 private static Class<?> getListGenericType(Field field) { try { return (Class<?>) ((java.lang.reflect.ParameterizedType) field.getGenericType()) .getActualTypeArguments()[0]; } catch (Exception e) { return null; } } // 转换包装类到基本类型 private static Object convertPrimitiveValue(Object value, Class<?> primitiveType) { if (value == null) { return null; } if (primitiveType == int.class) { return ((Number) value).intValue(); } else if (primitiveType == float.class) { return ((Number) value).floatValue(); } else if (primitiveType == double.class) { return ((Number) value).doubleValue(); } else if (primitiveType == long.class) { return ((Number) value).longValue(); } else if (primitiveType == boolean.class) { return (Boolean) value; } else if (primitiveType == char.class) { return ((String) value).charAt(0); } else if (primitiveType == byte.class) { return ((Number) value).byteValue(); } else if (primitiveType == short.class) { return ((Number) value).shortValue(); } return value; } }
使用示例
public static void main(String[] args) { Map<String, Object> flatMap = new HashMap<>(); flatMap.put("test", "t"); flatMap.put("testInt", 1); flatMap.put("b_testDouble", 1.1); flatMap.put("b_c_0_testFloat", 1.2); A a = ModelConverter.flatMapToNestedObject(flatMap, A.class); // 验证输出 System.out.println(a.test); // t System.out.println(a.testInt); // 1 System.out.println(a.b.testDouble); // 1.1 System.out.println(a.b.c.get(0).testFloat); // 1.2 }
内容的提问来源于stack exchange,提问作者Hari
相关产品推荐
相关产品推荐

