SpringBoot使用fastjosn作为消息转换器、fastjosn对日期的处理、自定义序列化器解决SerializerFeature兼容问题

笔者日常:说实话,这篇博客,过程有点曲折;我想搞明白为什么众多特性不兼容,自己跟了源码、看
                  了动态生成的class文件,可能水平不够,我找了很久还是没找到原因,于是请教了一位大神,
                  那么久过去了,一点回信也没有,哎~起码的尊重呢,可能太忙了吧。


SpringBoot使用fastjson作为消息转换器的步骤

第一步:引入fastjson依赖。

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.54</version>
</dependency>

第二步:配置消息转换器。

       上图只是最基本最简单的配置;在实际使用时,我们还可能根据自己的需求的不同,配置一些相关特性(如:防止中文乱码、字符串为null时输出””而非null,list为null时输出[]而非null,数值字段如果为null,输出为0而非null,Boolean默认输出false等等)。这里给出一个示例:

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * 自定义部分MVC配置
 *
 * @author JustryDeng
 * @date 2019/8/14 13:06
 */
@Component
public class MyWebMvcConfigurationSupport extends WebMvcConfigurationSupport {

    /**
     * 使用fastjson作为JSON消息转换器
     * 使用StringHttpMessageConverter作为String消息转换器
     * <p>
     * 注: 一般来讲,这两个消息消息转换器就是用于绝大部分情况了;
     * 如果业务环境情况等比较特殊,需要其他的消息转换器,
     * 那么再追加新的转换器即可
     * <p>
     * 注:JSON消息转换器需要引入fastjson依赖
     * StringHttpMessageConverter消息转换器需要引入springframework依赖
     *
     * @date 2019/8/14 13:06
     */
    @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        /// -> JSON消息转换器(采用阿里的fastjson)
        // 创建一个转换器对象;
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();

        // 个性化配置转换特性
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        // 配置:要格式化返回的json数据
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
        // 配置:把空的值的key也返回
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue);
        // 字段如果为null,输出为false,而非null
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullBooleanAsFalse);
        // 数值字段如果为null,输出为0,而非null
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullNumberAsZero);
        // List字段如果为null,输出为[],而非null;
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullListAsEmpty);
        // 字符类型字段如果为null,输出为"",而非null
        fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteNullStringAsEmpty);
        fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);

        // 处理中文乱码问题
        List<MediaType> fastMediaTypes = new ArrayList<>(4);
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);

        /// -> String消息转换器
        StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
        stringConverter.setDefaultCharset(Charset.forName("UTF-8"));
        stringConverter.setSupportedMediaTypes(fastMediaTypes);

        // 将convert添加到converters当中.
        converters.add(fastJsonHttpMessageConverter);
        converters.add(stringConverter);
        super.configureMessageConverters(converters);
    }
}

fastjson对日期类型的处理

声明对Date类型字段的处理方式较多,这里只给出三种比较常用的方式。

方式一配置了fastjson作为消息转换器后,在模型的对应日期字段上面使用@JSONField(format = "...")来指定格式

方式二在配置fastjson作为消息转换器的使用,通过.setDateFormat("...")指定全局Date字段的序列化格式

注:如果使用了.setDateFormat("...")的话,那么模型字段上通过 @JSONField(format = "...")指定日期序列化格式的方
       式,将不起作用。

方式三在配置fastjson作为消息转换器的时候,使用.setSerializerFeatures(SerializerFeature.WriteDateUseDateFormat)
               指定全局Date字段的默认序列化格式

注意事项

当上述三种方式或其中两种方式并存时,会采用优先级高的方式。三种方式的优先级:方式二 > 方式一 > 方式三, 即:

在fastjson消息转换器里配置.setDateFormat("...")

 

在字段模型上添加 @JSONField(format = "...") 

在fastjson消息转换器里配置.setSerializerFeatures(SerializerFeature.WriteDateUseDateFormat);


自定义序列化器(反序列化器)

声明fastjson的特性SerializerFeature有很多,但并不是每一种特性都一定和其它相互兼容的,这就可能造成:在
           消息转换器中配置的众多特性,部分生效了,部分没生效;这时我们可以考虑使用自定义的序列化器来解决
           这个问题
下面就简单演示自定义序列化器,并作出使用演示。

自定义序列化器、反序列化器

import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;

import java.lang.reflect.Type;

/**
 * 自定义序列化器、反序列化器
 *
 * @author JustryDeng
 * @date 2019/8/13 18:40
 */
public class MyDateSerializerAndDeserializer implements ObjectSerializer, ObjectDeserializer {

    /**
     * 序列化
     *
     * 程序给前端响应时, 就会将数据序列化为二进制流,进行传输
     */
    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) {
        SerializeWriter out = serializer.getWriter();
        if (fieldType == java.util.Date.class) {
            out.write("\"我是java.util.Date.class\"");
            return;
        } else if (fieldType == java.sql.Date.class) {
            out.write("\"我是java.sql.Date.class\"");
            return;
        }
        out.write(String.valueOf(object));
    }

    /**
     * 反序列化
     * 注:本文主要演示序列化, 反序列化这里就不作任何修改了
     *
     * 程序从前端获取请求的数据时, 就会将二进制流反序列化为数据类型T
     */
    @Override
    public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
        // do something
        return null;
    }

    @Override
    public int getFastMatchToken() {
        return 0;
    }

}

在fastjson消息转换器中配置使用自定义的序列化器

注:也可以(不在消息转换器里面统一指定序列化器、反序列化器,而)直接在字段上指定该字段使用哪个序列化器,如:

测试一下

相关Person类:

注:其中用到了lombok注解(这并不是必须的)。

相关DemoController类:

启动项目,访问http://localhost:8080/abc:

由此可见,自定义序列化器成功!


再次提示fastjson的特性SerializerFeature有很多,但并不是每一种特性都一定和其它相互兼容的,这就可能造成:在
                  消息转换器中配置的众多特性,部分生效了,部分没生效;这时我们可以考虑使用自定义的序列化器来解决
                  这个问题。


^_^ 如有不当之处,欢迎指正

^_^ 本文已经被收录进《程序员成长笔记(六)》,笔者JustryDeng

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值