com.alibaba.fastjson使用介绍

首先,介绍一下fastjson。fastjson是由alibaba开源的一套json处理器。与其他json处理器(如Gson,Jackson等)和其他的Java对象序列化反序列化方式相比,有比较明显的性能优势。

maven 添加配置:

<!-- 阿里fastjson包JSON转换-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>
String queryJson1 = JSON.toJSONString(studentQuery); //序列化
String queryJson2 = JSON.toJSONString(studentQuery, SerializerFeature.WriteDateUseDateFormat); //序列化时指定格式
String queryJson3 = JsonUtils.toJSONString(studentQuery, true); //自定义序列化格式
StudentQuery queryParam = JSON.parseObject(queryJson, StudentQuery.class); //反序列化

也可以自定义序列化JsonUtils类继承自JSON,解决序列化时字段格式和是否输出等,如下:

package com.demo.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

/**
 * @ProjectName: ssm.maven
 * @Package: com.demo.utils
 * @ClassName: JsonUtils
 * @Description: 自定义JSON
 * @Author: XXX
 * @Date: 2019/6/21 9:57
 * @Version: 1.0
 */
public class JsonUtils extends JSON {
    /**
     * 序列化配置
     * @param object
     * @param isFeatures
     * @return
     */
    public static String toJSONString(Object object, boolean isFeatures) {
        if (isFeatures) {
            SerializerFeature[] features = new SerializerFeature[3];
            features[0] = SerializerFeature.WriteDateUseDateFormat;
            features[1] = SerializerFeature.WriteMapNullValue;
            features[2] = SerializerFeature.WriteNullStringAsEmpty;
            return toJSONString(object, features);
        }
        else {
            return toJSONString(object);
        }
    }
}
View Code

案例一:

后端把Long类型的数据序列化成JSON后传给前端,前端可能会出现精度丢失的情况

例如:201511200001725439 这样一个Long类型的整数,传给前端后会变成201511200001725440

fastjson将Long类型转换成String类型,解决前后端交互,Java序列化JSON丢失精度问题的方法

解决方法:

  方法一:在后台将这个Long类型的字段转换成String类型的,风险比较大。

  方法二:使用fastjson的提供的注解,@JSONField(serializeUsing = ToStringSerializer.class)。        

需要导入包:

import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.ToStringSerializer;
@JSONField(serializeUsing = ToStringSerializer.class)
private Long id;

备注:  

  fastjson com.alibaba.fastjson.serializer 包下面提供了多种数据类型转换的注解。

另外自己也可以拓展这些注解,通过实现ObjectSerializer 接口来完成。

例如自定义ToStringSerializer将Long转String的代码:

import java.io.IOException;
import java.lang.reflect.Type;

import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;

public class LongToStringSerializer implements ObjectSerializer {
    public static final LongToStringSerializer instance = new LongToStringSerializer();

    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features)
                    throws IOException {
          SerializeWriter out = serializer.out;
          if (object == null) {
                out.writeNull();
                return;
          }
          String strVal = object.toString();
          out.writeString(strVal);
    }
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    
/**
* 利用fastJson替换掉jackson,且解决中文乱码问题
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

          FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
          FastJsonConfig fastJsonConfig = new FastJsonConfig();


          fastJsonConfig.setSerializerFeatures(
                           SerializerFeature.DisableCircularReferenceDetect,
                           SerializerFeature.WriteMapNullValue,
                           SerializerFeature.WriteNullNumberAsZero,
                           SerializerFeature.WriteNullStringAsEmpty,
                           SerializerFeature.WriteNullListAsEmpty,
                           SerializerFeature.WriteNullBooleanAsFalse,
                           SerializerFeature.WriteNonStringKeyAsString,
                           SerializerFeature.BrowserCompatible);       

        /**
         * 序列换成json时,将所有的long变成string,解决Long转json精度丢失的问题
         * 因为js中得数字类型不能包含所有的java long值
         */

          SerializeConfig serializeConfig = SerializeConfig.globalInstance;
          serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
          serializeConfig.put(Long.class, ToStringSerializer.instance);
          serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
          fastJsonConfig.setSerializeConfig(serializeConfig);


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


          fastConverter.setSupportedMediaTypes(fastMediaTypes);
          fastConverter.setFastJsonConfig(fastJsonConfig);
          converters.add(fastConverter);

    }

}

案例二:

让@ResponseBody用fastjson来序列化JSON返回到前端,如何在配置文件中设置

由于@ResponseBody返回的是默认用Jackson来序列化的,所以要让spring的消息转换器换成fastjson来序列化 

这样配置解决了如下问题:

      1、让@ResponseBody返回采用fastjson来序列化

      2、字段类型为Date,输出为"yyyy-MM-dd HH:mm:ss"

      3、是否输出值为null的字段

      4、字符类型字段如果为null,输出为"",而非null

      5、等等其他。。。

maven 添加配置:

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

在springmvc.xml中配置@ResponseBody使用fastjson

<!-- 配置注解驱动 重新设置@RequestMapping中对@ResponseBody以String类型消息转换器的字符集 -->
    <mvc:annotation-driven>
        <mvc:async-support default-timeout="3000"/>
        <mvc:message-converters register-defaults="true">
            <!-- 解决Controller返回json中文乱码问题 -->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <!-- <property name="supportedMediaTypes" value="text/html;charset=UTF-8" /> -->
                <!-- <property name="supportedMediaTypes" value="application/json;charset=UTF-8" > -->
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                        <value>application/xml;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
            <!-- 默认@ResponseBody返回的是jackson来序列化的, 所以要让spring的消息转换器换成fastjson来序列化 -->
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="fastJsonConfig">
                    <bean class="com.alibaba.fastjson.support.config.FastJsonConfig">
                        <!-- 序列化配置 -->
                        <property name="serializerFeatures">
                            <list value-type="com.alibaba.fastjson.serializer.SerializerFeature">
                                <!-- 字段类型为Date,输出为"yyyy-MM-dd HH:mm:ss" -->
                                <value>WriteDateUseDateFormat</value>
                                <!-- 是否输出值为null的字段,默认是false -->
                                <value>WriteMapNullValue</value>
                                <!-- 字符类型字段如果为null,输出为"",而非null -->
                                <value>WriteNullStringAsEmpty</value>
                                <!--<value>WriteNullNumberAsZero</value>-->
                                <!--<value>WriteNullListAsEmpty</value>-->
                                <!--<value>WriteNullBooleanAsFalse</value>-->
                                <!--<value>QuoteFieldNames</value>-->
                            </list>
                        </property>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
View Code

 如果上面配置文件中只是简单配置了一下fastjson来序列化,而没有配置那些“序列化配置”项目,则需要通过在实体对象属性上加注解方式实现了

package com.demo.model.vo;

import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.ToStringSerializer;
//import com.fasterxml.jackson.annotation.JsonFormat;
//import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * @ProjectName: maven
 * @Package: com.demo.model.vo
 * @ClassName: StudentVO
 * @Description: 返回请求对象
 * @Author: XXX
 * @Date: 2019/6/18 10:44
 * @Version: 1.0
 */
@Data
@ApiModel(value = "StudentVO", description = "返回请求对象")
public class StudentVO implements Serializable {
    @ApiModelProperty(value = "主键")
    @JSONField(serializeUsing = ToStringSerializer.class)
    //@JsonSerialize(using = com.fasterxml.jackson.databind.ser.std.ToStringSerializer.class)
    private Long id;

    @ApiModelProperty(value = "学生姓名")
    private String name;

    @ApiModelProperty(value = "学生年龄")
    private Integer age;

    @ApiModelProperty(value = "创建日期")
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    //@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createtime;
}
View Code

切记:这种配置只使用于@ResponseBody返回json格式,而不使用于通过在代码中通过JSON.toJSONString()方式来直接序列化的json,若想达到同样效果可以通过下面方式

方式一:

String queryJson = JSON.toJSONString(studentQuery, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);

方式二:使用上面提到的自定义序列化类JsonUtils

String queryJson = JsonUtils.toJSONString(studentQuery, true);

 

posted @ 2019-06-13 14:17  以德为先  阅读(50866)  评论(0编辑  收藏  举报