如何在Jackson的StdSerializer层为POJO转JSON结果添加customFields对象?
基于Jackson StdSerializer扩展已有JSON输出添加自定义字段
问题场景
现有POJO:
public class Person { public long id; public String someOtherId; public String vollName; public int alter; }
通过Mixin实现字段映射与过滤,生成JSON:
@JsonIncludeProperties( { "id", "name", "age", "customFields" } ) abstract class PersonM extends Person { @JsonProperty( "id" ) String someOtherId; @JsonProperty( "name" ) String vollName; @JsonProperty( "age" ) String alter; } // 序列化代码 ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn( Person.class, PersonM.class ); String body = mapper.writeValueAsString( person );
当前输出JSON:
{ "id": "xxxxxx", "name": "Aaaa Bbbb", "age": 111 }
需要扩展输出,添加customFields节点,内容基于POJO的id字段,且不允许修改原POJO:
{ "id": "xxxxxx", "name": "Aaaa Bbbb", "age": 111, "customFields": { "originalId": 333333 } }
解决方案:自定义StdSerializer复用默认序列化逻辑
我们可以通过自定义StdSerializer,先利用Jackson已有的序列化规则(包括Mixin配置)生成基础JSON节点,再添加自定义字段,避免重复实现所有字段的序列化。
1. 实现自定义序列化器
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; public class PersonSerializer extends StdSerializer<Person> { public PersonSerializer() { super(Person.class); } @Override public void serialize(Person person, JsonGenerator gen, SerializerProvider provider) throws IOException { // 获取已配置好的ObjectMapper(包含Mixin规则),将Person转换为基础ObjectNode ObjectMapper mapper = provider.getConfig().getObjectMapper(); ObjectNode objectNode = mapper.valueToTree(person); // 构建customFields节点并填充数据 ObjectNode customFields = mapper.createObjectNode(); customFields.put("originalId", person.id); // 将customFields添加到基础节点中 objectNode.set("customFields", customFields); // 将最终的JSON结构写入输出流 gen.writeTree(objectNode); } }
2. 注册序列化器并执行序列化
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); // 先注册Mixin配置,保证基础字段的映射规则生效 mapper.addMixIn(Person.class, PersonM.class); // 注册自定义序列化器 mapper.registerModule(new SimpleModule() .addSerializer(Person.class, new PersonSerializer())); // 构造测试对象 Person person = new Person(); person.id = 333333; person.someOtherId = "xxxxxx"; person.vollName = "Aaaa Bbbb"; person.alter = 111; // 序列化并输出 String body = mapper.writeValueAsString(person); System.out.println(body); } }
方案说明
- 复用已有逻辑:通过
mapper.valueToTree(person)直接利用已注册的Mixin规则生成基础JSON节点,无需重新定义所有字段的序列化规则 - 增量扩展:仅在基础节点上添加
customFields字段,避免重复造轮子 - 无侵入:完全在序列化层实现,不需要修改原POJO的代码
内容的提问来源于stack exchange,提问作者injecteer
相关产品推荐
相关产品推荐

