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
相关产品推荐
相关产品推荐

