首先,介紹一下fastjson。fastjson是由alibaba開源的一套json處理器。與其餘json處理器(如Gson,Jackson等)和其餘的Java對象序列化反序列化方式相比,有比較明顯的性能優點。html
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,解決序列化時字段格式和是否輸出等,以下:java
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); } } }
案例一:spring
例如:201511200001725439 這樣一個Long類型的整數,傳給前端後會變成201511200001725440json
fastjson將Long類型轉換成String類型,解決先後端交互,Java序列化JSON丟失精度問題的方法後端
解決方法:mvc
方法一:在後臺將這個Long類型的字段轉換成String類型的,風險比較大。app
方法二:使用fastjson的提供的註解,@JSONField(serializeUsing = ToStringSerializer.class)。 async
須要導入包:maven
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返回的是默認用Jackson來序列化的,因此要讓spring的消息轉換器換成fastjson來序列化
這樣配置解決了以下問題:
一、讓@ResponseBody返回採用fastjson來序列化
二、字段類型爲Date,輸出爲"yyyy-MM-dd HH:mm:ss"
三、是否輸出值爲null的字段
四、字符類型字段若是爲null,輸出爲"",而非null
五、等等其餘。。。
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>
若是上面配置文件中只是簡單配置了一下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; }
切記:這種配置只使用於@ResponseBody返回json格式,而不使用於經過在代碼中經過JSON.toJSONString()方式來直接序列化的json,若想達到一樣效果能夠經過下面方式
方式一:
String queryJson = JSON.toJSONString(studentQuery, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
方式二:使用上面提到的自定義序列化類JsonUtils
String queryJson = JsonUtils.toJSONString(studentQuery, true);