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

如何使用Jackson将嵌套POJO/JSON自动转为指定格式Map<String,String>

基于Jackson的嵌套对象转表单Map实现方案

完全可以直接借助Jackson完成转换,无需引入额外依赖,自动适配@JsonProperty配置的字段名,生成符合multipart/form-data提交要求的扁平化键值对。

实现思路

先将POJO对象或JSON字符串解析为Jackson的JsonNode树形结构,递归遍历所有节点:

  • 遇到嵌套对象节点时,按父键[子字段名]的规则拼接键前缀,继续向下遍历
  • 遇到字符串、数字、布尔等非嵌套的叶子节点时,直接将拼接好的完整键和节点转成的字符串值存入结果Map
    由于Jackson在序列化、转树结构时会默认读取@JsonProperty等注解配置,整个过程不需要手动做字段名映射。

可直接使用的工具代码

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class FormFlatMapUtil {
    // 全局复用ObjectMapper,避免重复创建开销
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /**
     * 从POJO对象直接转换为表单格式Map
     * @param pojo 待转换的嵌套POJO对象
     * @return 扁平化的表单键值对Map
     */
    public static Map<String, String> pojoToFormMap(Object pojo) throws IllegalArgumentException {
        JsonNode rootNode = OBJECT_MAPPER.valueToTree(pojo);
        Map<String, String> result = new HashMap<>();
        traverseNode(rootNode, "", result);
        return result;
    }

    /**
     * 从已序列化的JSON字符串转换为表单格式Map
     * @param jsonStr 嵌套结构JSON字符串
     * @return 扁平化的表单键值对Map
     */
    public static Map<String, String> jsonToFormMap(String jsonStr) throws IllegalArgumentException {
        try {
            JsonNode rootNode = OBJECT_MAPPER.readTree(jsonStr);
            Map<String, String> result = new HashMap<>();
            traverseNode(rootNode, "", result);
            return result;
        } catch (Exception e) {
            throw new IllegalArgumentException("JSON格式不合法,转换失败", e);
        }
    }

    /**
     * 递归遍历JsonNode树,拼接键名并收集叶子节点值
     */
    private static void traverseNode(JsonNode node, String currentPrefix, Map<String, String> result) {
        // 处理嵌套对象节点
        if (node.isObject()) {
            Iterator<Map.Entry<String, JsonNode>> fieldIterator = node.fields();
            while (fieldIterator.hasNext()) {
                Map.Entry<String, JsonNode> field = fieldIterator.next();
                String fieldName = field.getKey();
                JsonNode childNode = field.getValue();
                // 拼接新的键前缀
                String newPrefix = currentPrefix.isEmpty()
                        ? fieldName
                        : String.format("%s[%s]", currentPrefix, fieldName);
                traverseNode(childNode, newPrefix, result);
            }
            return;
        }
        // 叶子节点直接存入结果
        result.put(currentPrefix, node.asText());
    }
}

使用示例

对应给出的Request和Person类,调用方式如下:

public class Test {
    public static void main(String[] args) throws Exception {
        // 构造测试对象
        Person person = new Person();
        person.setDob("1995-10-01");
        person.setFirstName("San");
        person.setLastName("Zhang");

        Request request = new Request();
        request.setTransactionId("TX20240001");
        request.setPerson(person);

        // 直接从POJO转换
        Map<String, String> formMap = FormFlatMapUtil.pojoToFormMap(request);
        /*
        转换结果和手动put的内容完全一致:
        transaction_id = TX20240001
        person[dob] = 1995-10-01
        person[first_name] = San
        person[last_name] = Zhang
        */

        // 从已序列化的JSON转换
        String requestJson = OBJECT_MAPPER.writeValueAsString(request);
        Map<String, String> formMapFromJson = FormFlatMapUtil.jsonToFormMap(requestJson);
    }
}

扩展说明

  • 当前实现支持任意层级的对象嵌套,会自动生成a[b][c]格式的合法表单键名
  • 如果后续需要处理数组字段,只需在traverseNode方法中增加数组节点的判断分支,按key[索引]的规则拼接键名即可
  • 整个过程完全复用现有Jackson序列化配置,包括@JsonProperty、命名策略等,不需要额外做适配

内容的提问来源于stack exchange,提问作者Alexander

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:36:24