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

如何配置Jackson实现以Java类名为键的对象序列化与反序列化

Jackson适配单键类标识格式的通用解决方案

这个需求可以通过自定义Jackson的通用序列化/反序列化器,注册为全局模块实现,支持所有Java类型的自动适配,不需要为单个字段额外加注解。

核心实现逻辑

第三方返回的格式本质是将对象类型作为唯一键、对象值作为键值的包装结构,我们只需要在序列化/反序列化阶段处理这个包装逻辑即可。


1. 编写通用反序列化器(处理第三方返回的JSON解析)

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;

public class ClassWrappedDeserializer extends JsonDeserializer<Object> {
    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        ObjectNode node = p.getCodec().readTree(p);
        // 判断是否为单键值对的包装结构
        if (node.size() == 1) {
            Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
            Map.Entry<String, JsonNode> onlyField = fields.next();
            String className = onlyField.getKey();
            JsonNode valueNode = onlyField.getValue();
            try {
                // 加载类并将值反序列化为对应类型
                Class<?> clazz = Class.forName(className);
                return p.getCodec().treeToValue(valueNode, clazz);
            } catch (ClassNotFoundException e) {
                throw new JsonMappingException(p, "无法识别的类类型: " + className, e);
            }
        }
        // 非包装结构走默认反序列化
        return p.getCodec().treeToValue(node, Object.class);
    }
}

2. 编写通用序列化器(生成符合第三方要求的JSON格式)

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

public class ClassWrappedSerializer extends JsonSerializer<Object> {
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        // 键为对象类的全限定名
        gen.writeFieldName(value.getClass().getName());
        // 值为对象本身的序列化结果
        gen.writeObject(value);
        gen.writeEndObject();
    }
}

3. 注册为全局模块,Spring Boot自动生效

将自定义序列化/反序列化器封装为Jackson模块,Spring Boot会自动扫描注册所有Module类型的Bean:

import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Date;

@Configuration
public class JacksonConfig {

    @Bean
    public SimpleModule classWrappedModule() {
        SimpleModule module = new SimpleModule("ClassWrappedModule");
        // 为需要适配的类型注册序列化/反序列化器,按需添加即可
        // 示例添加Date类型支持
        module.addSerializer(Date.class, new ClassWrappedSerializer());
        module.addDeserializer(Object.class, new ClassWrappedDeserializer());
        // 如果需要适配自定义类型,直接追加即可,比如:
        // module.addSerializer(自定义类.class, new ClassWrappedSerializer());
        return module;
    }
}

效果验证

你提供的示例JSON可以直接解析为对应实体类:

// 实体类定义
@Data
public class Task {
    @JsonProperty("task-id")
    private Long taskId;
    @JsonProperty("task-created-on")
    private Date taskCreatedOn;
}

解析后taskCreatedOn会自动转换为java.util.Date类型,序列化时也会自动生成{"java.util.Date": 时间戳}的格式。

如果需要适配更多类型,只需要在classWrappedModule方法中追加对应类型的序列化器注册即可,无需修改核心逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:36:05