如何为Jackson中的B类配置自定义序列化器,实现A类对象序列化时objB字段转为基于val2计算的字符串
当然可以!给B类定制序列化器是最优解
完全不用给A类写全局序列化器,直接针对B类实现自定义序列化逻辑就可以达成你想要的效果,而且后续A类增减字段都不需要修改任何序列化代码,非常灵活。
具体实现步骤:
编写B类的自定义序列化器
继承Jackson的StdSerializer<B>,重写serialize方法,在方法里根据val2计算出你需要的字符串,然后直接输出这个字符串即可,不用再序列化B的嵌套结构。示例代码:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; public class BCustomSerializer extends StdSerializer<B> { public BCustomSerializer() { this(null); } public BCustomSerializer(Class<B> t) { super(t); } @Override public void serialize(B b, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { // 这里写你基于val2计算MY_STRING的逻辑,比如示例中的拼接规则 String myString = "CALC_VAL_" + b.getVal2(); jsonGenerator.writeString(myString); } }给B类绑定这个序列化器
有两种灵活的方式可选:- 直接在B类上添加
@JsonSerialize注解指定序列化器(侵入式,适合可以修改B类代码的场景):import com.fasterxml.jackson.databind.annotation.JsonSerialize; @JsonSerialize(using = BCustomSerializer.class) public class B { private int val2; // 构造器、getter/setter方法省略 } - 或者在
ObjectMapper中全局注册序列化器(非侵入式,适合不想修改B类源码的场景):ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addSerializer(B.class, new BCustomSerializer()); mapper.registerModule(module);
- 直接在B类上添加
测试序列化效果
现在序列化A类对象时,objB字段就会自动变成你计算出的字符串,而不是嵌套的JSON对象:A a = new A(); a.setVal(10); B b = new B(); b.setVal2(20); a.setObjB(b); ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(a); // 输出结果:{"val":10,"objB":"CALC_VAL_20"}
为什么这个方案更优?
- 完全遵循开闭原则:A类后续添加或删除字段,根本不需要改动序列化相关代码,Jackson会自动处理其他字段的序列化逻辑。
- 职责单一:序列化逻辑只和B类相关,维护起来更清晰,后续如果要修改MY_STRING的计算规则,只需要调整B的序列化器即可,不会影响A类的其他逻辑。
内容的提问来源于stack exchange,提问作者user007
相关产品推荐
相关产品推荐

