Jaskson精講第7篇-類繼承關(guān)系下的JSON序列化與反序列化JsonTypeInfo

Jackson是Spring Boot(SpringBoot)默認(rèn)的JSON數(shù)據(jù)處理框架,但是其并不依賴于任何的Spring 庫。有的小伙伴以為Jackson只能在Spring框架內(nèi)使用,其實(shí)不是的,沒有這種限制。它提供了很多的JSON數(shù)據(jù)處理方法、注解,也包括流式API、樹模型、數(shù)據(jù)綁定,以及復(fù)雜數(shù)據(jù)類型轉(zhuǎn)換等功能。它雖然簡單易用,但絕對不是小玩具,更多的內(nèi)容我會寫成一個(gè)系列,5-10篇文章,請您繼續(xù)關(guān)注我。

本篇文章是系列文章的第7篇,主要是為大家介紹一下,在Java 類繼承的情況下如何實(shí)現(xiàn)父類及子類的JSON序列化與反序列化。

一、繼承關(guān)系對象構(gòu)建

首先構(gòu)建一個(gè)ClsShape類表示形狀。

public class ClsShape {
}

構(gòu)建一個(gè)ClsCircle 類表示圓形。并添加了一系列的lombok注解,Data表示提供get、set、toString、hashCode等方法;EqualsAndHashCode注解在有繼承關(guān)系的字類中使用;AllArgsConstructor和NoArgsConstructor分別提供全參和無參構(gòu)造方法。

@Data
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
public class ClsCircle extends ClsShape {
  Integer radius;    //弧度
}

構(gòu)建一個(gè)長方形類ClsRectangle ,成員變量width寬度,height高度。

@Data
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
public class ClsRectangle extends ClsShape {
  private Integer width;
  private Integer height;
}

構(gòu)建一個(gè)ClsView類,表示畫面。畫面中有很多的ClsShape形狀,所以用一個(gè)List封裝。

@Data
public class ClsView {
  private List<ClsShape> shapes;
}

二、序列化與反序列化測試

基礎(chǔ)的形狀類及畫面類寫完之后,下面的代碼是用來完成:對象到Json字符串的序列化過程,和Json字符串反序列化為Java對象的過程代碼。

@Test
void testJSON2Object() throws IOException {
  ClsRectangle rectangle = new ClsRectangle(7,9); //構(gòu)建正方形對象
  ClsCircle circle = new ClsCircle(8); //構(gòu)建長方形對象
  List<ClsShape> shapes = new ArrayList<>();  //List<多種形狀>
  shapes.add(circle);
  shapes.add(rectangle);
  ClsView view = new ClsView();  //將List放入畫面View
  view.setShapes(shapes);

  ObjectMapper mapper = new ObjectMapper();
  System.out.println("-- 序列化 --");
  String jsonStr = mapper.writeValueAsString(view);
  System.out.println(jsonStr);

  System.out.println("-- 反序列化 --");
  ClsView deserializeView = mapper.readValue(jsonStr, ClsView.class);
  System.out.println(deserializeView);

}

大家看最終在控制臺的輸出結(jié)果如下:序列化的過程是正常的,但是反序列化的時(shí)候報(bào)錯(cuò)了。

-- 序列化 --
{"shapes":[{"radius":8},{"width":7,"height":9}]}

-- 反序列化 --
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "radius" (class com.example.demo.javabase.ClsShape), not marked as ignorable (0 known properties: ])
 at [Source: (String)"{"shapes":[{"radius":8},{"width":7,"height":9}]}"; line: 1, column: 23] (through reference chain: com.example.demo.javabase.ClsView["shapes"]->java.util.ArrayList[0]->com.example.demo.javabase.ClsShape["radius"])

拋出異常的主要原因是我們用來接收反序列化的結(jié)果時(shí),使用的是List<ClsShape>,Java程序并不明確的知道,這個(gè)ClsShape形狀是圓形ClsCircle,還是正方形ClsRectangle。所以無法將字符串正確的反序列化為java對象。

三、@JsonTypeInfo注解加到父類定義上

為了解決上面的這種繼承關(guān)系對象的反序列化出現(xiàn)的問題,jackson為我們提供了JsonTypeInfo注解,把它加在父類定義上面即可。

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public class ClsShape {
}

在父類定義上面加上@JsonTypeInfo注解之后,序列化與反序列化的輸出結(jié)果如下。

-- 序列化 --
{"shapes":[
{"@class":"com.example.demo.javabase.ClsCircle","radius":8},
{"@class":"com.example.demo.javabase.ClsRectangle","width":7,"height":9}
]}
-- 反序列化 --
ClsView(shapes=[ClsCircle(radius=8), ClsRectangle(width=7, height=9)])

值得注意的是在序列化之后的java字符串中,每個(gè)Json對象都包含了一個(gè)新的屬性@class,這也是該對象在繼承關(guān)系下能夠反序列化為正確的java對象(@class的值的類對象)的關(guān)鍵所在。

四、@JsonTypeInfo注解加到包含父類的成員變量上面

@JsonTypeInfo注解不僅可以加在父類的定義上面,也可以加到包含父類的成員變量上面。序列化和反序列化的結(jié)果和第三小節(jié)中的內(nèi)容是一樣的。

@Data
public class ClsView {
  @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
  private List<ClsShape> shapes;
}

歡迎關(guān)注我的博客,里面有很多精品合集

  • 本文轉(zhuǎn)載注明出處(必須帶連接,不能只轉(zhuǎn)文字):字母哥博客。

覺得對您有幫助的話,幫我點(diǎn)贊、分享!您的支持是我不竭的創(chuàng)作動力! 。另外,筆者最近一段時(shí)間輸出了如下的精品內(nèi)容,期待您的關(guān)注。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容