Spring Boot如何配置全局JSON序列化、反序列化

起因

当我们在写web接口时,常以JSON格式返回,但是对于一些日期、枚举之类的处理通常需要加@JsonFormat@JsonValue@JsonSerialize之类的注解进行特定的序列化处理。那么对于公用的序列化处理该如何实现呢?

知识储备

  1. 了解@JsonFormat@JsonValue@JsonSerialize之类的注解,方便进行比较
  2. 了解Jackson序列化
  3. 了解@EnableWebMvc的作用,点击这里查看

四种全局序列化方式

Spring Boot默认采用Jackson进行序列化,所以提供的四种全局序列化方式都是针对于Jackson,对于fastJson方式下文中也会顺便提一下。本文以对枚举类的全局序列化来举例。

1.通过@JsonComponent(推荐)

首先话不多说先看个例子。
定义枚举类

public enum CurrCode implements BaseEnum {
    RMB("156", "rmb"), USD("840", "usd");

    private String code;
    private String desc;

    CurrCode(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    @JsonCreator
    public static CurrCode of(@JsonProperty("code") String c) {
        for (CurrCode value : CurrCode.values()) {
            if (value.getCode().equals(c)) {
                return value;
            }
        }
        return null;
    }

    public String getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }

    @Override
    public String toString() {
        return "CurrCode{" +
                "code='" + code + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }

    @Override
    public String getValue() {
        return getCode();
    }
}

定义配置类

@JsonComponent
public class JacksonComponent {

    public static class CurrCodeJsonSerializer extends JsonSerializer<CurrCode> {
        @Override
        public void serialize(CurrCode currCode, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString(currCode.getCode());
        }
    }

}

分析
查看@JsonComponent源码

@Component that provides JsonSerializer,JsonDeserializer or KeyDeserializer implementations to be registered with Jackson when JsonComponentModule is in use. Can be used to annotate implementations directly or a class that contains them as inner-classes.

翻译:@Component,提供JsonSerializer,JsonDeserializer或KeyDeserializer实现,以便在使用JsonComponentModule时向Jackson进行注册。可用于直接注解实现或包含它们作为内部类的类。

@JsonComponent
public class CustomerJsonComponent {

 public static class Serializer extends JsonSerializer<Customer> {
	 // ...
 }

 public static class Deserializer extends JsonDeserializer<Customer> {
	 // ...
 }

}

上面源码里给出的例子在@JsonComponent注解所修饰的类里面添加继承JsonSerializer的内部类,spring就会自动帮助我们将定义的序列化类注册到jackson里去。这个过程使用的仍然是Spring Boot自动配置web mvc,这样静态资源不会失效。推荐使用这种方式实现全局JSON序列化。
补充@JsonComponent注解value用来指定注册到Spring容器里的Bean Name,type用来指定对哪些类进行了序列化或反序列化处理。scope指定对在作用范围。

2.Jackson2ObjectMapperBuilderCustomizer

使用Jackson2ObjectMapperBuilderCustomizer实现全局序列化、反序列化,这个过程使用的仍然是Spring Boot自动配置web mvc,这样静态资源不会失效。

 @Configuration
public class LocalDateTimeSerializerConfig {

    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> builder.serializerByType(LocalDateTime.class,
                new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern)));
    }

}

3.ObjectMapper

使用ObjectMapper实现全局序列化、反序列化,这个过程使用的仍然是Spring Boot自动配置web mvc,这样静态资源不会失效。

@Configuration
public class LocalDateTimeSerializerConfig {

    @Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
    private String pattern;

    @Bean
    public ObjectMapper customObjectMapper() {
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern)));
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }

}

4.WebMvcConfigurationSupport配置(了解)

@Configuration
public class JacksonConfig extends WebMvcConfigurationSupport {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(CurrCode.class, new CurrCodeJsonSerializer());
        objectMapper.registerModule(simpleModule);
        // 配置null值序列化成空字符串
        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
                jsonGenerator.writeString("");
            }
        });
        //这里是fastJSON的配置方式,更多的内容可以查看SerializerFeature
        // FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        // converter.setFeatures(SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullNumberAsZero,
        //         SerializerFeature.WriteNullBooleanAsFalse, SerializerFeature.WriteNullListAsEmpty);
        converter.setObjectMapper(objectMapper);
        converters.add(converter);
    }

    public static class CurrCodeJsonSerializer extends JsonSerializer<CurrCode> {
        @Override
        public void serialize(CurrCode currCode, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeObject(currCode.getCode());
        }
    }
}

分析
继承WebMvcConfigurationSupport类主要是需要往web mvc配置中添加对于我们要特殊处理类的转换器(HttpMessageConverter的子类),由于我们使用的是Jackson序列化对象所以需要往转换里添加Jackson提供的转换器即MappingJackson2HttpMessageConverter。如果使用fastjson可以使用转换器FastJsonHttpMessageConverter。
补充:
1.WebMvcConfigurationSupport会屏蔽Spring Boot的自动配置。这样会导致自动配置的静态资源路径(classpath:/META/resources/,classpath:/resources/,classpath:/static/,classpath:/public/)无法访问。
2.上面的配置类同样可以实现WebMvcConfigurer,实现同名的configureMessageConverters方法具体同上。但是需要这个配置类起作用需要在配置类上加上@EnableWebMvc注解。
3.@EnableWebMvc注解同样会导致自动配置的静态资源路径无法访问,也会导致@JsonFormat之类的注解无法工作。

测试

定义一个测试的接口如下

@RestController
public class JacksonController {

    @GetMapping(path = "/test")
    public Param getTest() {
        Param param = new Param();
        param.setCurrCode(CurrCode.RMB);
        return param;
    }

}

利用postman工具发送请求,查看返回结果,如下可以看出返回的是枚举类的code而不是枚举名称。

在这里插入图片描述

总结

以上四种方式都能实现全局JSON序列化,但是为了保证避免静态资源路径无法访问以及@JsonFormat之类的注解无法工作的问题,推荐使用第一种方法使用@JsonComponent注解来实现全局JSON序列化或者第二三两种方案都可。

代码地址:
https://github.com/nestorbian/spring-boot-examples/tree/master/jackson-full-config

参考文章:
https://www.cnblogs.com/wang-meng/p/9163875.html
https://blog.csdn.net/zxc123e/article/details/84636521

  • 11
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot提供了自定义JSON序列化反序列化的方式,可以通过实现`JsonSerializer`和`JsonDeserializer`接口来实现。 自定义JSON序列化: 1. 创建一个类,实现`JsonSerializer`接口,并重写`serialize`方法。在该方法中,可以自定义对象的序列化逻辑,将对象转换为JSON格式的字符串。 2. 在需要进行自定义序列化的字段上,使用`@JsonSerialize(using = YourSerializer.class)`注解,将自定义的序列化类指定为该字段的序列化器。 自定义JSON反序列化: 1. 创建一个类,实现`JsonDeserializer`接口,并重写`deserialize`方法。在该方法中,可以自定义JSON字符串的反序列化逻辑,将JSON字符串转换为对象。 2. 在需要进行自定义反序列化的字段上,使用`@JsonDeserialize(using = YourDeserializer.class)`注解,将自定义的反序列化类指定为该字段的反序列化器。 示例代码如下: ```java // 自定义序列化器 public class CustomSerializer extends JsonSerializer<YourClass> { @Override public void serialize(YourClass value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 自定义序列化逻辑 gen.writeString(value.toString()); } } // 自定义反序列化器 public class CustomDeserializer extends JsonDeserializer<YourClass> { @Override public YourClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 自定义反序列化逻辑 String value = p.getValueAsString(); return new YourClass(value); } } // 在需要进行自定义序列化反序列化的字段上使用注解 public class YourClass { @JsonSerialize(using = CustomSerializer.class) private String field1; @JsonDeserialize(using = CustomDeserializer.class) private String field2; // 省略其他代码 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值