Jackson序列化子类B为父类A的技术问题求助
解决Jackson将子类B序列化为父类A的问题
这种情况我之前也碰到过,Jackson默认的类型处理逻辑确实容易卡壳——明明B没有额外字段,想把它当成A序列化却抛出异常,还不想用子类型声明(毕竟那样序列化反序列化都会绑定到B),也不能加容器类。下面给你几个实用的解决方案:
方案一:给子类B加序列化注解
直接在B类上标注@JsonSerialize(as = A.class),告诉Jackson序列化B的时候就按A的规则来,生成的JSON和A实例完全一致,不会带任何子类标识:
import com.fasterxml.jackson.databind.annotation.JsonSerialize; @JsonSerialize(as = A.class) public class B extends A { public B(int a) { super(a); } }
这个方法最简单,属于代码侵入式的,但改动很小,只需要加个注解。
方案二:全局配置ObjectMapper
如果不想修改类的代码,可以给ObjectMapper注册一个自定义模块,指定B类型的序列化规则:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.core.JsonGenerator; import java.io.IOException; public class JacksonConfig { public static ObjectMapper getCustomMapper() { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 自定义B的序列化器,把它当作A来序列化 module.addSerializer(B.class, new StdSerializer<B>(B.class) { @Override public void serialize(B value, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeObject((A) value); } }); mapper.registerModule(module); return mapper; } }
之后用这个配置好的ObjectMapper来序列化,所有B实例都会被处理成A的格式。
方案三:局部使用ObjectWriter指定类型
如果只是个别场景需要这么处理,不用全局配置或改类,直接用writerFor指定序列化类型就行:
B bInstance = new B(123); ObjectMapper mapper = new ObjectMapper(); // 生成一个针对A类型的Writer ObjectWriter writer = mapper.writerFor(A.class); String json = writer.writeValueAsString(bInstance); // 输出结果:{"a":123},和A实例序列化的结果完全一样
这个方式最灵活,适合只在特定地方需要转换的场景。
为什么原来会抛异常?
Jackson默认会识别对象的实际类型,哪怕B没有额外字段,在某些配置下(比如开启了类型检测、或者反序列化时JSON隐含了类型信息),它会因为找不到对应的类型映射规则而抛出异常。上面的方法本质都是强制Jackson把B当作A来处理,跳过了对B类型的特殊检测,自然就解决了问题。
内容的提问来源于stack exchange,提问作者Vitali Melamud
相关产品推荐
相关产品推荐

