You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:15:33