SpringBoot2.x系列教程16--SpringBoot中自定义JSON序列化器和反序列化器

简介: 前言在上一章节中,壹哥 给大家介绍了在SpringMVC框架中,我们可以使用HttpMessageConverter转换器类来转换HTTP请求和响应信息,并且可以实现对JSON信息的格式转换。我们知道,JSON是前后端信息传输的主要载体,我们大多数传递的参数都是利用JSON完成的,所以JSON是非常重要和常用的。而JSON信息本身也比较复杂,其中有些细节需要我们注意,比如JSON的序列化和反序列化。一. 序列化与反序列化简介1. 概述HttpMessageConverter在转换http请求和响应的过程中,可以将对象转为JSON,这个过程我们可以称之为序列化;反过来也可以将JSON转为

前言

在上一章节中,壹哥 给大家介绍了在SpringMVC框架中,我们可以使用HttpMessageConverter转换器类来转换HTTP请求和响应信息,并且可以实现对JSON信息的格式转换。我们知道,JSON是前后端信息传输的主要载体,我们大多数传递的参数都是利用JSON完成的,所以JSON是非常重要和常用的。而JSON信息本身也比较复杂,其中有些细节需要我们注意,比如JSON的序列化和反序列化。

一. 序列化与反序列化简介

1. 概述

HttpMessageConverter在转换http请求和响应的过程中,可以将对象转为JSON,这个过程我们可以称之为序列化;反过来也可以将JSON转为对象,这就是反序列化。

2. @JsonComponent注解

在Spring Boot中,默认是使用Jackson来对JSON信息进行序列化和反序列化的。那么除了可以用默认的之外,我们也可以编写自己的JsonSerializer和JsonDeserializer类来进行自定义操作。

自定义序列化器(serializers)通常是通过Module方式注册到Jackson中,但在Spring Boot中提供了@JsonComponent注解作为替代方案,它能帮我们更为轻松的将序列化器注册到Spring Beans中

我们可以直接在JsonSerializer 或 JsonDeserializer类上使用 @JsonComponent注解,该注解允许我们将带该注解的类公开为Jackson序列化器或反序列化器,而无需再手动将其添加到ObjectMapper。我们还可以在包含序列化程序/反序列化程序作为内部类的类上使用它,如下例所示:

importjava.io.*;
importcom.fasterxml.jackson.core.*;
importcom.fasterxml.jackson.databind.*;
importorg.springframework.boot.jackson.*;
@JsonComponentpublicclassExample {
publicstaticclassSerializerextendsJsonSerializer<SomeObject> {
// ...    }
publicstaticclassDeserializerextendsJsonDeserializer<SomeObject> {
// ...    }
}

ApplicationContext 中的所有 @JsonComponent bean都会自动注册到Jackson,因为 @JsonComponent是用 @Component进行注解的,所以应用通常的组件扫描规则。

SpringBoot还提供了JsonObjectSerializer和JsonObjectDeserializer 基类,它们在序列化对象时为标准的Jackson版本提供了有用的替代方案。

二. 自定义序列化与反序列化

接下来我就带大家创建一个项目,在这里实行JSON的序列化和反序列化。

1. 创建新项目

为了讲解序列化与反序列化的实现,我们创建一个新的工程,创建过程类似于之前,此处略过。最后完整的项目结构如下,各位可以参考创建。

2. 实现JsonSerializer序列化

我们首先创建一个CustomeJackSon类,类上带有@JsonComponent注解。在该类内部编写一个静态内部类,继承JsonSerializer,并重写Serialize()方法。在重写的serialize()方法中实现对JSON信息中Double类型数据的格式化。

/***使用@JsonComponent注释会自动被注册到Jackson中.**/@JsonComponentpublicclassCustomeJackSon {
/*** 自定义序列化器,格式化数值*/publicstaticclassMySerializerextendsJsonSerializer<Double> {
privateDecimalFormatdf=newDecimalFormat("##.00");
/*** 序列化操作,继承JsonSerializer,重写Serialize函数*/@Overridepublicvoidserialize(Doublevalue, JsonGeneratorjsonGenerator, SerializerProviderserializerProvider) throwsIOException {
jsonGenerator.writeString(df.format(value));
        }
    }
}

3. 反序列化JsonDeserializer实现

然后我们再编写一个静态内部类,继承JsonDeserializer类,重写deserialize()方法,自定义自己的反序列化逻辑。在这里实现对JSON中日期信息的格式化。

/*** 使用@JsonComponent注释会自动被注册到Jackson中.*/@Slf4j@JsonComponentpublicclassCustomeJackSon {
/*** 自定义反序列化器,格式化时间*/publicstaticclassMyDeserializerextendsJsonDeserializer<Date> {
privateSimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd");
@OverridepublicDatedeserialize(JsonParserjsonParser, DeserializationContextdeserializationContext) throwsIOException {
Datedate=null;
try {
date=sdf.parse(jsonParser.getText());
            } catch (ParseExceptione) {
e.printStackTrace();
            }
returndate;
        }
    }
}

4. 构建Bean对象

4.1 常用json注解简介

  • @JsonIgnoreProperties:
    此注解是类注解,作用是在json序列化时将Java bean中的某些属性忽略掉,序列化和反序列化都受影响。
  • @JsonIgnore:
    此注解用于属性或者方法上(最好是属性上),作用和上面的@JsonIgnoreProperties一样。
  • @JsonFormat:
    此注解用于属性或者方法上(最好是属性上),可以方便的把Date类型直接转化为我们想要的模式,比如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")  
  • @JsonSerialize:
    此注解用于属性或者getter方法上,用于在序列化时嵌入我们自定义的序列化器,比如序列化一个double时在其后面限制两位小数点。
  • @JsonDeserializ:
    此注解用于属性或者setter方法上,用于在反序列化时嵌入我们自定义的反序列化器,比如反序列化一个Date类型的时间字符串。
  • @JsonCreator与@JsonProperty:
    该注解的作用就是指定反序列化时替代无参构造函数,构造方法的参数前面需要加上@JsonProperty注解。

4.2 完整的Java bean实体类

接下来我再创建一个User实体类,注意这个类上的一些关于JSON的注解。

packagecom.yyg.boot.domain;
importcom.fasterxml.jackson.annotation.JsonCreator;
importcom.fasterxml.jackson.annotation.JsonIgnoreProperties;
importcom.fasterxml.jackson.annotation.JsonProperty;
importcom.fasterxml.jackson.databind.annotation.JsonDeserialize;
importcom.fasterxml.jackson.databind.annotation.JsonSerialize;
importcom.yyg.boot.json.CustomeJackSon;
importlombok.Data;
importlombok.ToString;
importjava.util.Date;
/*** @NoArgsConstructor* @AllArgsConstructor 表示序列化时忽略的属性*/@Data@ToString@JsonIgnoreProperties(value= {"word"})
publicclassUser {
/*** 注意:在进行JSON序列化和反序列化时,要么提供一个无参的构造方法,要么在其他构造方法上添加@JsonCreator注解.*/privateStringname;
privateintage;
privatebooleansex;
privateDatebirthday;
privateStringword;
privatedoublesalary;
@JsonCreatorpublicUser(@JsonProperty("name") Stringname, @JsonProperty("age") intage, @JsonProperty("sex") booleansex, @JsonProperty("birthday") Datebirthday,
@JsonProperty("word") Stringword, @JsonProperty("salary") doublesalary) {
super();
this.name=name;
this.age=age;
this.sex=sex;
this.birthday=birthday;
this.word=word;
this.salary=salary;
    }
/*** 反序列化一个固定格式的Date*/@JsonDeserialize(using=CustomeJackSon.MyDeserializer.class)
publicvoidsetBirthday(Datebirthday) {
this.birthday=birthday;
    }
/*** 序列化指定格式的double格式*/@JsonSerialize(using=CustomeJackSon.MySerializer.class)
publicdoublegetSalary() {
returnsalary;
    }
}

注意:

当json在反序列化时,默认选择类的无参构造函数创建类对象,当没有无参构造函数时则会报错,@JsonCreator注解的作用就是指定反序列化时用的无参构造函数。构造方法的参数前面需要加上@JsonProperty,否则会报错!

例如:

@JsonCreatorpublicPerson(@JsonProperty("id") Stringid) {
this.id=id;
}

5. 编写Controller

然后我们再编写一个Controller,封装2个Web接口用于测试,接收传递过来的请求参数,并将User实体类转为JSON格式的信息响应到前端。

packagecom.yyg.boot.web;
importcom.yyg.boot.domain.User;
importlombok.extern.slf4j.Slf4j;
importorg.springframework.web.bind.annotation.*;
importjava.util.Date;
@Slf4j@RestControllerpublicclassUserController {
/*** 将对象转为json字符串-->序列化*/@GetMapping("/user/{salary}")
publicUserhome(@PathVariable("salary") Longsalary) {
returnnewUser("一一哥", 30, true, newDate(), "程序员", salary);
    }
/*** 将一个json转化为对象-->反序列化*/@RequestMapping(value="user")
publicStringgetValue(@RequestBodyUseruser) {
log.warn("user="+user.toString());
returnuser.toString();
    }
}

6. 编写入口类

最后编写一个项目入口类。

packagecom.yyg.boot;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
/*** json的序列化与反序列化*/@SpringBootApplicationpublicclassSerializeApplication {
publicstaticvoidmain(String[] args) {
SpringApplication.run(SerializeApplication.class, args);
    }
}

7. 运行程序,检查结果

重启项目后,我们进行项目测试。

7.1 序列化测试

我们先来看看序列化的测试结果,会发现JSON中携带的double类型数据后面自动带了2位小数点。

7.2 反序列化测试

因为我们要接受一个JSON参数,所以可以利用postman进行反序列化测试,执行后可以看到返回的JSON数据中,我们的日期信息被转换成了我们规定的格式。

最终我们在SpringBoot项目中实现了自定义的JSON序列化与反序列化操作。

结语

这样通过一些简单配置,我们就把整个项目中所有的JSON序列化和反序列化进行了统一的设置,以后开发时,我们项目中的JSON格式一般都有统一的要求,就可以采用本文中的方法进行序列化和反序列化,你学会了吗?

今日小作业:

增加一个学生注册功能,注册信息中要带有学生体重、学费、生日等信息,对这些信息请做统一处理。

相关文章
|
3月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
230 1
|
3月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
245 1
|
4月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
713 5
|
6月前
|
JSON Java 数据格式
Spring Boot返回Json数据及数据封装
在Spring Boot中,接口间及前后端的数据传输通常使用JSON格式。通过@RestController注解,可轻松实现Controller返回JSON数据。该注解是Spring Boot新增的组合注解,结合了@Controller和@ResponseBody的功能,默认将返回值转换为JSON格式。Spring Boot底层默认采用Jackson作为JSON解析框架,并通过spring-boot-starter-json依赖集成了相关库,包括jackson-databind、jackson-datatype-jdk8等常用模块,简化了开发者对依赖的手动管理。
646 3
|
7月前
|
存储 Java 编译器
说一说关于序列化/反序列化中的细节问题
我是小假 期待与你的下一次相遇 ~
136 1
|
7月前
|
JSON Java 数据库连接
|
8月前
|
存储 安全 IDE
说一说序列化与反序列化中存在的问题
本文详细解析了Java中的序列化机制,包括序列化的概念、实现方式及应用场景。通过Student类的实例演示了对象的序列化与反序列化过程,并分析了`Serializable`接口的作用以及`serialVersionUID`的重要意义。此外,文章还探讨了如何通过自定义`readObject()`方法增强序列化的安全性,以及解决可序列化单例模式中可能产生的多实例问题。最后提供了代码示例和运行结果,帮助读者深入理解序列化的原理与实践技巧。
211 2
|
8月前
|
JSON JavaScript 前端开发
Go语言JSON 序列化与反序列化 -《Go语言实战指南》
本文介绍了 Go 语言中使用 `encoding/json` 包实现 JSON 与数据结构之间的转换。内容涵盖序列化(`Marshal`)和反序列化(`Unmarshal`),包括基本示例、结构体字段标签的使用、控制字段行为的标签(如 `omitempty` 和 `-`)、处理 `map` 和切片、嵌套结构体序列化、反序列化未知结构(使用 `map[string]interface{}`)以及 JSON 数组的解析。最后通过表格总结了序列化与反序列化的方法及类型要求,帮助开发者快速掌握 JSON 数据处理技巧。
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
584 1
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。

热门文章

最新文章