Springboot官网学习(7、Web应用程序【三Spring Web MVC 之自定义JSON序列化器和反序列化器,让你的项目起飞】)

上一节Springboot官网学习(7、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到了吗,没有的话评论吧,我会一一回复的

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值