《Spring Boot 3实战案例合集》现已囊括超过60篇精选实战文章,并且此合集承诺将永久持续更新,为您带来最前沿的技术资讯与实践经验。欢迎积极订阅,享受不断升级的知识盛宴!订阅用户将特别获赠合集内所有文章的最终版MD文档(详尽学习笔记),以及完整的项目源码,助您在学习道路上畅通无阻。
环境:SpringBoot2.7.18
1. 简介
在之前的一篇文章中详细的介绍了如何优雅的定制JSON数据格式的响应,文章地址如下:
在该篇文章中,我们介绍了通过两种主要方式来自定义JSON的序列化:注解和编程方式。注解方式允许我们在类、字段或方法上使用特定的标记来指示JSON序列化的行为。然而,有时我们可能需要更细粒度的控制,这时就可以使用编程方式来实现。
本篇文章将重点介绍如何通过编程方式自定义JSON的序列化和反序列化。编程方式通常涉及到实现特定的接口或扩展框架提供的类,以便在序列化和反序列化过程中插入自定义的逻辑。
在Spring Boot中使用Jackson库时,我们可以创建自定义的序列化器和反序列化器来处理JSON的转换。自定义序列化器需要实现JsonSerializer<T>、JsonObjectSerializer 接口,而自定义反序列化器则需要实现JsonDeserializer<T>、JsonObjectDeserializer接口。这些接口提供了必要的方法来定义如何将Java对象转换为JSON字符串(序列化),以及如何将JSON字符串转换为Java对象(反序列化)。
2. 实战案例
在Spring Boot环境下你可以自定义 JsonSerializer、JsonDeserializer 或 KeyDeserializer 的实现类上直接使用 @JsonComponent 注解。也可以在包含序列化器/解序列化器作为内部类的类中使用。
2.1 自定义JsonSerializer/Deserializer
@JsonComponentpublic class PackJsonComponent {// 自定义序列化public static class Serializer extends JsonSerializer<User> {@Overridepublic void serialize(User value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {jgen.writeStartObject() ;jgen.writeStringField("name", value.getName()) ;jgen.writeNumberField("age", value.getAge()) ;jgen.writeEndObject() ;}}// 自定义反序列化public static class Deserializer extends JsonDeserializer<User> {@Overridepublic User deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {ObjectCodec codec = jsonParser.getCodec() ;JsonNode tree = codec.readTree(jsonParser) ;String name = tree.get("name").textValue() ;int age = tree.get("age").intValue() ;// 为了区分这里故意做了+操作,以表示生效long id = tree.get("id").longValue() + 1000L ;return new User(id, name, age) ;}}}
上面自定义PackJsonComponent类中定义了序列化和反序列化组件,他们的父类都指定了泛型的类型,这里你也可以指定Object,在进行处理时再进行类型的判断。
测试接口
@RestController@RequestMapping("/jackson")public class JacksonController {@GetMapping("/user")public User queryUser() {return new User(1L, "张三", 10) ;}@PostMapping("/save")public User queryUser(@RequestBody User user) {return user ;}}// User对象public class User {private Long id ;private String name ;private Integer age ;// getter, setter}
测试/queryUser接口

测试/save接口

注意:在测试该/save接口时,你需要先将序列号的类注释了,不然你看不到效果。
ApplicationContext容器中的所有 @JsonComponent Bean 都会自动向 Jackson 注册。因为 @JsonComponent 是用 @Component 元标注的,所以通常的组件扫描规则也适用。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Componentpublic @interface JsonComponent {// ...}
接下来介绍另外一种自定义的方式。
2.2 自定义JsonObjectSerializer/Deserializer
Spring Boot 还提供了 JsonObjectSerializer 和 JsonObjectDeserializer 基类,在序列化对象时,它们为标准的 Jackson 版本提供了有用的替代方法。
public class PackJsonComponent {public static class Serializer extends JsonObjectSerializer<User> {protected void serializeObject(User value, JsonGenerator jgen, SerializerProvider provider) throws IOException {jgen.writeNumberField("id", value.getId()) ;jgen.writeStringField("name", value.getName()) ;jgen.writeNumberField("age", value.getAge());// 添加新的属性jgen.writeStringField("nation", "中国🇨🇳") ;// 自定义写入其它的对象Map<String, Object> params = new HashMap<>() ;params.put("q", "java") ;params.put("s", "pack") ;jgen.writeObjectField("params", params) ;}}public static class Deserializer extends JsonObjectDeserializer<User> {protected User deserializeObject(JsonParser jsonParser,DeserializationContext context,ObjectCodec codec,JsonNode tree) throws IOException {long id = nullSafeValue(tree.get("id"), Long.class) + 1L ;String name = nullSafeValue(tree.get("name"), String.class);int age = nullSafeValue(tree.get("age"), Integer.class) ;return new User(id, name, age) ;}}}
通过以上的方式都可以自定义JSON对象的序列化和反序列化。
需要注意:你不能在序列化时直接通过writeObject方法输出当前方法参数的value对象
// 不允许这样操作,这会报错;但你可以像上面那样输出其它的对象jgen.writeObject(value);
上面不管你通过什么方式自定义JSON的序列化和反序列化,都将只针对你指定的泛型类型有效,其它对象类型不会生效。
以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏
推荐文章
性能优化!Spring Boot 通过10个技巧优化API接口响应时间
@Transactional用错!严重影响性能,Spring Boot 事务最佳实践
任务重复执行?SpringBoot 一个注解轻松搞定分布式任务调度
面试官:说说@Configuration与@Component有什么区别?
通过Spring AOP结合SpEL表达式:构建强大且灵活的权限控制体系
新一代WebFlux框架核心技术Reactor响应式编程基本用法
【网关大解密】SpringCloud Gateway 打造极简网关API服务,你一定没用过





