You need to enable JavaScript to run this app. Jackson序列化继承HashMap的类时自定义字段被忽略如何通用解决?
优惠活动
大模型
产品
解决方案
定价
更多

Jackson序列化继承HashMap的类时自定义字段被忽略如何通用解决?

问题根因

Jackson默认序列化逻辑中,若目标类实现了Map接口,会优先使用MapSerializer处理,仅序列化Map存储的键值对,类中显式声明的成员属性会被直接跳过,这就是setField设置的属性没有输出的原因。

通用解决方案

你无需修改生成的实体类,也不用为每个Map子类单独编写序列化器,通过自定义BeanSerializerModifier实现全局适配即可,步骤如下:

1. 实现通用序列化器

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.MapSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.Map;

public class MapWithExtraFieldsSerializer extends StdSerializer<Map<?, ?>> {
    private final MapSerializer defaultMapSerializer;

    public MapWithExtraFieldsSerializer(MapSerializer defaultSerializer) {
        super(Map.class, false);
        this.defaultMapSerializer = defaultSerializer;
    }

    @Override
    public void serialize(Map<?, ?> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        // 先序列化Map本身存储的键值对
        defaultMapSerializer.serialize(value, gen, provider);
        // 再序列化类中显式声明的自定义属性
        provider.getConfig()
                .introspect(provider.constructType(value.getClass()))
                .findProperties()
                .stream()
                // 过滤掉Map/Object自带的通用属性
                .filter(prop -> !"empty".equals(prop.getName()) && !"class".equals(prop.getName()))
                .forEach(prop -> {
                    try {
                        prop.serializeAsField(value, gen, provider);
                    } catch (Exception e) {
                        throw new RuntimeException("序列化Map子类属性失败", e);
                    }
                });
        gen.writeEndObject();
    }
}

2. 实现序列化器修改器

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.ser.std.MapSerializer;
import java.util.Map;

public class MapSubTypeSerializerModifier extends BeanSerializerModifier {
    @Override
    public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
        // 只处理非JDK原生的Map子类(即你从YAML生成的类)
        if (Map.class.isAssignableFrom(beanDesc.getBeanClass()) 
            && !beanDesc.getBeanClass().getName().startsWith("java.util.")) {
            if (serializer instanceof MapSerializer) {
                return new MapWithExtraFieldsSerializer((MapSerializer) serializer);
            }
        }
        return serializer;
    }
}

3. 注册到ObjectMapper全局生效

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

// 初始化ObjectMapper时注册配置
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new SimpleModule() {
    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.addBeanSerializerModifier(new MapSubTypeSerializerModifier());
    }
});

配置完成后再序列化MyObject就能输出你期望的结构,所有从YAML生成的继承HashMap的类都可以自动适配,无需额外调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 04:24:03