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

如何用Jackson将Key/Value结构的JSON反序列化为Java对象?

通用Jackson反序列化方案:将Attributes结构JSON映射到Java对象

针对你遇到的这种把字段包装在attributes数组中的非标准JSON,我们可以通过自定义Jackson反序列化器+BeanDeserializerModifier实现通用映射,无需为每个Java类编写单独逻辑,同时支持嵌套结构。

核心实现思路

  1. 自定义AttributesDeserializer:负责解析attributes数组,将key-value结构转换为标准的键值对JSON结构,递归处理嵌套的attributes对象。
  2. 通过BeanDeserializerModifier全局注册这个反序列化器,让所有自定义JavaBean自动应用该逻辑。

代码实现

1. 通用Attributes反序列化器

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.io.IOException;
import java.util.Iterator;

public class AttributesDeserializer extends JsonDeserializer<Object> {
    private final ObjectMapper objectMapper;

    public AttributesDeserializer(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode rootNode = p.getCodec().readTree(p);
        // 识别并处理attributes包裹的结构
        if (rootNode.has("attributes")) {
            JsonNode attributesNode = rootNode.get("attributes");
            ObjectNode targetNode = objectMapper.createObjectNode();

            Iterator<JsonNode> attrIterator = attributesNode.elements();
            while (attrIterator.hasNext()) {
                JsonNode attr = attrIterator.next();
                String fieldKey = attr.get("key").asText();
                JsonNode fieldValue = attr.get("value");

                // 递归处理嵌套的attributes结构
                if (fieldValue.isObject() && fieldValue.has("attributes")) {
                    fieldValue = deserializeNestedValue(fieldValue, ctxt);
                }
                targetNode.set(fieldKey, fieldValue);
            }
            // 将转换后的节点映射为目标Java类
            return objectMapper.treeToValue(targetNode, ctxt.getContextualType().getRawClass());
        }
        // 非attributes结构直接映射(兼容标准JSON)
        return objectMapper.treeToValue(rootNode, ctxt.getContextualType().getRawClass());
    }

    private JsonNode deserializeNestedValue(JsonNode valueNode, DeserializationContext ctxt) throws IOException {
        Object nestedObj = deserialize(valueNode.traverse(objectMapper), ctxt);
        return objectMapper.valueToTree(nestedObj);
    }
}

2. 全局注册反序列化器

通过BeanDeserializerModifier将自定义反序列化器应用到所有JavaBean:

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;

public class AttributesDeserializerModifier extends BeanDeserializerModifier {
    private final ObjectMapper objectMapper;

    public AttributesDeserializerModifier(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        // 跳过Java原生类,只对自定义Bean应用
        if (beanDesc.getBeanClass().isPrimitive() || beanDesc.getBeanClass().equals(String.class)) {
            return deserializer;
        }
        return new AttributesDeserializer(objectMapper);
    }
}

3. 使用示例

配置ObjectMapper并测试嵌套JSON的解析:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

public class JacksonDemo {
    public static void main(String[] args) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.setDeserializerModifier(new AttributesDeserializerModifier(objectMapper));
        objectMapper.registerModule(module);

        // 包含嵌套结构的测试JSON
        String testJson = "{ \"attributes\": [\n" +
                "    { \"key\": \"name\", \"value\": \"Jane\" },\n" +
                "    { \"key\": \"age\", \"value\": 34 },\n" +
                "    { \"key\": \"address\", \"value\": {\n" +
                "        \"attributes\": [\n" +
                "            { \"key\": \"street\", \"value\": \"123 Main St\" },\n" +
                "            { \"key\": \"city\", \"value\": \"New York\" }\n" +
                "        ]\n" +
                "    } }\n" +
                "]}";

        Person person = objectMapper.readValue(testJson, Person.class);
        System.out.println("姓名: " + person.name);
        System.out.println("年龄: " + person.age);
        System.out.println("街道: " + person.address.street);
        System.out.println("城市: " + person.address.city);
    }

    // 自定义JavaBean
    static class Person {
        String name;
        Integer age;
        Address address;
    }

    static class Address {
        String street;
        String city;
    }
}

方案优势

  • 通用性:无需为每个Java类编写自定义反序列化代码,全局生效
  • 嵌套支持:递归处理value中的attributes结构,适配复杂层级的JSON
  • 兼容性:同时支持标准JSON格式的解析,不影响原有业务逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 08:40:35