Springboot官网学习(Web应用程序【Spring Web MVC 之自定义JSON序列化器和反序列化器,让你的项目起飞】)
上一节springboot之Web应用程序【Spring Web MVC 之HttpMessageConverters消息转换器】我们学习了自己定制消息转换器,SpringMVC框架使用HttpMessageConverter转换器类来转换http请求数据和响应数据。如果需要配置的话,通过注解@Bean来返回我们自己配置的消息转换器。HttpMessageConverter在转换http请求和响应的过程中,就需要将java对象转为JSON字符串,也叫做序列化;或者将JSON字符串转为java对象,也叫做反序列化。
那么我们有时候就会遇到一些需求,比如格式化日期格式,比如说格式化double类型保留两位小数,比如字符串转换成日期格式等这些需求在工作中都是会遇到的,难道我们就去对每一个对象修改吗,显然这样是不合理的,所以通过自定义序列化器和反序列化器是非常有必要的。
如果使用Jackson来序列化和反序列化JSON数据,则可能需要编写自己的JsonSerializer和JsonDeserializer类。自定义序列化程序通常是通过模块向Jackson进行注册的,但是Spring Boot提供了另一种@JsonComponent注释,使直接注册Spring Bean更加容易。
这是官网的说法。
import java.io.*; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.databind.*; import org.springframework.boot.jackson.*; @JsonComponent public class Example { public static class Serializer extends JsonSerializer<SomeObject> { // ... } public static class Deserializer extends JsonDeserializer<SomeObject> { // ... } }
这是官网给出的例子。
那么我们就按照这个例子来写一个自己的序列化和反序列化器吧
代码里面有一些注释,如果不懂的,请评论,我会简答。
package com.osy.config; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import org.springframework.boot.jackson.JsonComponent; import java.io.IOException; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; // 使用此注解,让springboot来进行扫描,并且识别他是我们自定义的序列化器和反序列化器 @JsonComponent public class MyJsonSerializer { public static class Serializer extends JsonSerializer<Object> { private DecimalFormat decimalFormat = new DecimalFormat("#.00"); private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** * 自定义序列化器,这里看他源码是带泛型的,所以这里一定要带上泛型,可以像我一样使用Object类,如果不写,启动就会报错 * Cannot pass `null` as type to register serializer for(血类史:耽搁了我大概十分钟) * @param o * @param jsonGenerator * @param serializerProvider * @throws IOException */ @Override public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { System.out.printf("o = " + o); if(o instanceof Double){ jsonGenerator.writeString(decimalFormat.format(o)); }else if(o instanceof Date){ jsonGenerator.writeString(simpleDateFormat.format(o)); }else{ jsonGenerator.writeObject(o); } } } public static class Deserializer extends JsonDeserializer<Date> { private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private SimpleDateFormat simpleDateFormatSimple = new SimpleDateFormat("yyyy-MM-dd"); @Override public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { Date date = null; // 检查格式,如果是yyyy-MM-dd",那么就解析,如果不是,就再次解析yyyy-MM-dd HH:mm:ss try { date = simpleDateFormatSimple.parse(jsonParser.getText()); } catch (ParseException e) { try { date = simpleDateFormat.parse(jsonParser.getText()); }catch (ParseException e1){ e1.printStackTrace(); throw new RuntimeException("时间类型解析错误,请传入正确的日期格式"); } } return date; } } }
看完是不是就知道怎么用了,打上@JsonComponent注解springboot就会扫描到并且进行配置,注意,这个类一定要写在启动类下面的包下。如果不明白为什么,请看另一边博客Springboot官网学习(2、Maven构建项目)
那么这里在说一下jackson包给我们提供了一些便捷的注解:
@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注解。
那么我们就要验证一下:
建立实体User类(我这里就之验证一下序列化)
package com.osy.entity; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.osy.config.MyJsonSerializer; import java.util.Date; public class User { // 这里一定要指定我们自定义的序列化器,不打注解不生效,我以为他们默认全部生效,后来想了一下,不合理。有些是不需要的 @JsonSerialize(using = MyJsonSerializer.Serializer.class) private Double price; @JsonSerialize(using = MyJsonSerializer.Serializer.class) private Date birthDay; public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public Date getBirthDay() { return birthDay; } public void setBirthDay(Date birthDay) { this.birthDay = birthDay; } }
创建启动类和控制器,返回User对象
import com.osy.entity.User; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Date; @RestController @SpringBootApplication public class Application { @RequestMapping("/getUser") public User getUser() { User user = new User(); user.setPrice(20); // 看结果是否返回20.00 user.setBirthDay(new Date()); // 看结果是否返回我们定义的格式yyyy-MM-dd HH:mm:ss return user; } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
然后访问了一波,看结果:
{“price”:“20.00”,“birthDay”:“2020-06-18 23:29:04”},这就是达到了我们自定义序列化的效果了,这种操作我相信80%的项目应该都有这种需求吧,get到了吗,没有的话评论吧,我会一一回复的
一个相信努力就会有结果的程序员,以兴趣驱动技术!
------ CoderOu

浙公网安备 33010602011771号