1. 程式人生 > >記一次序列化的JSON解析問題

記一次序列化的JSON解析問題

目錄

    • 一、問題初探
    • 二、問題原因
    • 三、解決問題

一、問題初探

我今天在使用Ribbon 遠端呼叫的時候

消費者去消費服務端所提供的服務,在使用Post請求中的PostForEntity傳遞引數的時候,我是這樣寫的

Ribbon 消費端:

User 是一個 Pojo 物件,程式碼如下:

public class User {

    private Integer id;
    private String name;

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    get... and set ...
}

Ribbon 服務端:

就是一個很簡單的Ribbon 遠端呼叫的一個操作,報如下錯誤:

跟入原始碼:

然後就不明覺厲了,第一開始比較煩躁,一直以為是消費端的問題,因為錯誤是從消費服務端報出來的。後來經過冷靜發現,上述程式碼是在處理服務端響應的時候報出來的,應該還是服務端報錯來的錯誤。

2019-04-14 13:56:27.183  WARN 3500 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not construct instance of com.service.provider.pojo.User: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.service.provider.pojo.User: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
 at [Source: java.io.PushbackInputStream@25979c35; line: 1, column: 2]

程式碼並不能看懂什麼意思,求助google,從stackoverflow上找到了問題的答案:

沒有加預設的建構函式?????? 這是什麼鬼? 預設的建構函式和JSON解析有什麼關係?

但是能夠解決問題了,我檢查了一遍我一直以為我的值沒有傳遞過去,但我看已經傳遞到服務端了(避免了一個白痴問題)。

二、問題原因

====================================華麗的分割線====================================

事實印證了我是個菜比。

事情是這樣的

Ribbon的消費者向服務者提供的資料轉換是要把物件轉換為二進位制資料,這個過程稱之為序列化

而服務端收到二進位制的資料再轉換為對應的物件,這個過程稱之為反序列化

序列化會把物件儲存在磁碟中,或允許直接在網路中直接傳輸物件

反序列化就是收到二進位制的資料,再轉換為對應的物件。

而實現物件序列化的方法有兩種:

1. 實現序列化介面

2. 提供無參建構函式

而上面報錯的原因就是因為沒有提供預設的建構函式或者實現序列化介面!!!!!

三、解決問題

新增無參建構函式

解決問題一,再上面的Pojo類上新增預設的建構函式

public class User {

    private Integer id;
    private String name;

    public User(){}
    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    get and set...
}

再次呼叫介面,客戶端能夠打印出來對應的日誌