最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringMVC Json自定義序列化和反序列化的操作方法

 更新時間:2021年01月29日 10:08:57   作者:黃鷹  
這篇文章主要介紹了SpringMVC Json自定義序列化和反序列化的操作方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

需求背景

需求一:SpringMVC構(gòu)建的微服務(wù)系統(tǒng),數(shù)據(jù)庫對日期的存儲是Long類型的時間戳,前端之前是默認(rèn)使用Long類型時間,現(xiàn)在前端框架改動,要求后端響應(yīng)數(shù)據(jù)時,Long類型的時間自動變成標(biāo)準(zhǔn)時間格式(yyyy-MM-dd HH:mm:ss)。

涉及到這個轉(zhuǎn)換的范圍挺大,所有的實體表都有創(chuàng)建時間createTime和修改時間updateTime,目前的主要訴求也是針對這兩個字段,并且在實體詳情數(shù)據(jù)和列表數(shù)據(jù)都存在,需要一個統(tǒng)一的方法,對這兩個字段進(jìn)行處理。

需求二:前端請求上傳的JSON報文,String類型的內(nèi)容,可能會出現(xiàn)前后有空格的現(xiàn)象,如果前端框架未對此問題進(jìn)行處理,后端收到的JSON請求反序列化為對象時,就會出現(xiàn)String類型的值,前后有空格,現(xiàn)需要一個統(tǒng)一的處理方法,對接收的String類型屬性執(zhí)行trim方法。

解決方案

SpringMVC默認(rèn)的JSON框架為jackson,也可以使用fastjson。

jackson框架

自定義序列化

如果項目使用jackson框架做json序列化,推薦的方案是使用@JsonSerialize注解,示例代碼如下:

@JsonSerialize(using = CustomDateSerializer.class) 
private Long createTime;

@JsonSerialize(using = CustomDateSerializer.class) 
private Long updateTime;

CustomDateSerializer類的實現(xiàn)示例如下:

public class CustomDateSerializer extends JsonSerializer<Long> {

 @Override
 public void serialize(Long aLong, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  Date date = new Date(aLong);
  jsonGenerator.writeString(sdf.format(date));
 }
}

這種方案的好處如下:

  • 自定義的實現(xiàn)類可以復(fù)用
  • 精準(zhǔn)到需要轉(zhuǎn)換處理的字段,不受限于createTime和updateTime,更貼近于需求

缺點就是需要轉(zhuǎn)換的字段都需要使用注解,工作量有點大

當(dāng)然有其他的統(tǒng)一處理方案,這里不贅述。

自定義反序列化

在jackson框架上實現(xiàn)自定義序列化,也是非常方便的,繼承SimpleModule類即可:

@Component
public class StringTrimModule extends SimpleModule {

 public StringTrimModule() {
  addDeserializer(String.class, new StdScalarDeserializer<String>(String.class) {
   @Override
   public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException {
    String value = jsonParser.getValueAsString();
    if (StringUtils.isEmpty(value)) {
      return value;
    }
    return value.trim();
   }
  });
 }
}

fastjson框架

如果工程里出現(xiàn)這個依賴:

<dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>fastjson</artifactId>
 <version>1.2.62</version>
</dependency>

說明此工程使用的json框架為fastjson,那么jackson的@JsonSerialize就不會有觸發(fā)入口了,我們來看看fastjson的處理方式。

自定義序列化

相應(yīng)的,使用fastjson會有相應(yīng)的配置類,示例如下:

/**
 * 統(tǒng)一輸出是采用fastJson
 *
 * @return
 */
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
 //convert轉(zhuǎn)換消息的對象
 FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();

 //處理中文亂碼問題
 List<MediaType> fastMediaTypes = new ArrayList<>();
 fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
 fastConverter.setSupportedMediaTypes(fastMediaTypes);

 //是否要格式化返回的json數(shù)據(jù)
 FastJsonConfig fastJsonConfig = new FastJsonConfig();
 fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
 // 添加指定字段的值轉(zhuǎn)換處理
 fastJsonConfig.setSerializeFilters(new CustomerDateFilter());
 // FastJson禁用autoTypeSupport
 fastJsonConfig.getParserConfig().setAutoTypeSupport(false);
 fastConverter.setFastJsonConfig(fastJsonConfig);

 return new HttpMessageConverters(fastConverter);
}

這里需要添加fastjson對字段值的處理(上述代碼已添加這行代碼),如

// 添加指定字段的值轉(zhuǎn)換處理
fastJsonConfig.setSerializeFilters(new CustomerDateFilter());

CustomerDateFilter為自行實現(xiàn)的類,代碼如下:

public class CustomerDateFilter implements ValueFilter {

 @Override
 public Object process(Object object, String name, Object value) {
  if (FieldConstants.CREATE_TIME.equalsIgnoreCase(name) || FieldConstants.UPDATE_TIME.equalsIgnoreCase(name)) {
   // 屬性名為createTime, updateTime進(jìn)行轉(zhuǎn)換處理
   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
   sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));

   if(value instanceof Long) {
    Long time = (Long) value;
    Date date = new Date(time);
    return sdf.format(date);
   } else {
    return value;
   }
  }
  return value;
 }
}

這樣就可以把所有響應(yīng)對象中出現(xiàn)的createTime和updateTime字段統(tǒng)一處理了,無論列表數(shù)據(jù)還是單個對象數(shù)據(jù),非常方便。缺點就是除此之外的字段,如果還做不到全系統(tǒng)統(tǒng)一,就需要單獨處理。

SerializeFilter定制序列化

支持SerializeFilter定制序列化的擴(kuò)展編程接口有以下幾個,可根據(jù)實際需要進(jìn)行擴(kuò)展:

  • PropertyPreFilter: 根據(jù)PropertyName判斷是否序列化;
  • PropertyFilter: 根據(jù)PropertyName和PropertyValue來判斷是否序列化;
  • NameFilter: 修改Key,如果需要修改Key,process返回值則可;
  • ValueFilter: 修改Value;
  • BeforeFilter: 序列化時在最前添加內(nèi)容;
  • AfterFilter: 序列化時在最后添加內(nèi)容;
  • 自定義反序列化

fastJson提供了序列化過濾器,來實現(xiàn)自定義序列化改造,但沒有提供反序列化過濾器,來實現(xiàn)對應(yīng)的功能。

方案:@JSONField注解

回到對JSON報文String類型的值執(zhí)行trim操作,官網(wǎng)支持@JSONField注解的屬性設(shè)置(要求fastJson版本1.2.36以上):

@JSONField(format="trim")
private String name;

在JSON報文反序列化時,該實體的name屬性會自動執(zhí)行trim方法進(jìn)行處理。

此方案只有逐個添加注解,工作量較大。

方案:實現(xiàn)ObjectDeserializer接口

ObjectDeserializer接口為可以實現(xiàn)自定義反序列化實現(xiàn)接口,配合ParserConfig的全局設(shè)置,也可以達(dá)到預(yù)期的效果,合建StringTrimDeserializer類,對String進(jìn)行處理:

/**
 * @title: StringTrimDeserializer
 * @description: 把String類型的內(nèi)容統(tǒng)一做trim操作
 */
public class StringTrimDeserializer implements ObjectDeserializer {

 @Override
 public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
  // JSON String反序列化的邏輯比較復(fù)雜,在StringCodec的基礎(chǔ)上,對其結(jié)果調(diào)用trim方法
  Object obj = StringCodec.instance.deserialze(parser, type, fieldName);
  if (obj instanceof String) {
   String str = (String) obj;
   return (T) str.trim();
  }
  return (T) obj;
 }

 @Override
 public int getFastMatchToken() {
  return JSONToken.LITERAL_STRING;
 }
}

相應(yīng)在,在HttpMessageConverters類fastJsonHttpMessageConverters方法內(nèi)中增加String類的反序列化設(shè)置:

// 設(shè)置String類的全局反序列化規(guī)則:自動完成trim操作
ParserConfig.getGlobalInstance().putDeserializer(String.class, new StringTrimDeserializer());

tips:

在StringTrimDeserializer類實現(xiàn)方法中為什么不直接parser.getLexer().stringVal()得到值后執(zhí)行trim方法,而是調(diào)用StringCodec.instance的實現(xiàn)方法?

StringCodec是fastJson默認(rèn)的String類型的反序列化邏輯類,里面要處理的類型有String、StringBuffer、StringBuilder等,還有各種的集合、數(shù)組結(jié)構(gòu),涉及的nextToken值都不相同,總之,對String文本的反序列化,實現(xiàn)邏輯和應(yīng)對的場景都比較復(fù)雜,而此次的需求只是對String執(zhí)行trim操作,復(fù)雜的邏輯還是交給StringCodec來處理,站在StringCodec的基礎(chǔ)上,對其結(jié)果執(zhí)行trim方法就可以達(dá)到預(yù)期目標(biāo)。

小結(jié)

今天這篇是記錄Json自定義序列化和反序列化的實踐方案,開始實施前先確認(rèn)工程里使用的框架是哪個,否則就會出現(xiàn)添加了@JsonSerialize注解,搞了大半天沒有效果,回頭一看框架是fastjson,沒有觸發(fā)入口,當(dāng)然得不到預(yù)期效果,小小建議,希望對你有幫助。

到此這篇關(guān)于SpringMVC Json自定義序列化和反序列化的文章就介紹到這了,更多相關(guān)SpringMVC 序列化和反序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中synchronized正確使用方法解析

    Java中synchronized正確使用方法解析

    這篇文章主要介紹了Java中syncronized正確使用方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • JVM入門之內(nèi)存結(jié)構(gòu)(堆、方法區(qū))

    JVM入門之內(nèi)存結(jié)構(gòu)(堆、方法區(qū))

    JVM 基本上是每家招聘公司都會問到的問題,它們會這么無聊問這些不切實際的問題嗎?很顯然不是。由 JVM 引發(fā)的故障問題,無論在我們開發(fā)過程中還是生產(chǎn)環(huán)境下都是非常常見的
    2021-06-06
  • java synchronized 鎖機(jī)制原理詳解

    java synchronized 鎖機(jī)制原理詳解

    synchronized關(guān)鍵字是JAVA中常用的同步功能,提供了簡單易用的鎖功能。這篇文章主要介紹了Java中synchronized關(guān)鍵字引出的多種鎖問題,需要的朋友可以參考下
    2021-08-08
  • SpringBoot實現(xiàn)攔截器、過濾器、監(jiān)聽器過程解析

    SpringBoot實現(xiàn)攔截器、過濾器、監(jiān)聽器過程解析

    這篇文章主要介紹了SpringBoot實現(xiàn)攔截器、過濾器、監(jiān)聽器過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • java實現(xiàn)二維數(shù)組轉(zhuǎn)json的方法示例

    java實現(xiàn)二維數(shù)組轉(zhuǎn)json的方法示例

    這篇文章主要介紹了java實現(xiàn)二維數(shù)組轉(zhuǎn)json的方法,涉及java數(shù)組遍歷及json格式數(shù)據(jù)構(gòu)造相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • springboot實現(xiàn)excel表格導(dǎo)出幾種常見方法

    springboot實現(xiàn)excel表格導(dǎo)出幾種常見方法

    在日常的開發(fā)中避免不了操作Excel,下面這篇文章主要給大家介紹了關(guān)于springboot實現(xiàn)excel表格導(dǎo)出的幾種常見方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • BeanUtils.copyProperties復(fù)制屬性失敗的原因及解決方案

    BeanUtils.copyProperties復(fù)制屬性失敗的原因及解決方案

    這篇文章主要介紹了BeanUtils.copyProperties復(fù)制屬性失敗的原因及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Jpa中Specification的求和sum不生效原理分析

    Jpa中Specification的求和sum不生效原理分析

    這篇文章主要為大家介紹了Jpa中Specification的求和sum不生效原理示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • java 通過反射遍歷所有字段修改值的實例代碼

    java 通過反射遍歷所有字段修改值的實例代碼

    這篇文章主要介紹了java 通過反射遍歷所有字段修改值,通過java 的反射,遍歷所有字段,進(jìn)行一個判斷,取出來的值是帶有圖片鏈接的,進(jìn)行操作,省去了很多代碼,理解也很容易,下面跟隨小編看下實例代碼吧
    2021-05-05
  • Java?中的整型數(shù)據(jù)類型((byte,?short,?int,?long?)的取值范圍及使用不同的整型的場景分析

    Java?中的整型數(shù)據(jù)類型((byte,?short,?int,?long?)的取值范圍及使用不同的整型的場景

    Java中的整型數(shù)據(jù)類型包括byte、short、int和long,每種類型都有不同的內(nèi)存占用和取值范圍,選擇合適的整型類型取決于具體需求,如內(nèi)存敏感場景、性能考量和避免整數(shù)溢出,示例代碼展示了如何聲明和初始化不同整型變量,并打印它們的最大值,感興趣的朋友一起看看吧
    2025-03-03

最新評論

平远县| 韩城市| 乌鲁木齐县| 日喀则市| 黑龙江省| 宁陵县| 太康县| 东乌珠穆沁旗| 巩义市| 象州县| 光山县| 买车| 临洮县| 凤庆县| 郁南县| 葫芦岛市| 修文县| 临朐县| 海安县| 桂东县| 高要市| 旬阳县| 扎赉特旗| 永善县| 乃东县| 图片| 贺州市| 固阳县| 秦皇岛市| 定兴县| 土默特右旗| 景洪市| 郓城县| 黎川县| 鄂托克前旗| 同江市| 建阳市| 阿拉尔市| 高要市| 麻城市| 滦平县|