記錄Jackson和Lombok的坑


記錄Jackson和Lombok的坑

今天遇到Jackson反序列化json缺少了字段,后來研究下發現是Jackson的機制和Lombok生成的setter不一致,導致沒有正確調用setter。

復現

Java實體類

@Data
public class DemoData{
    private Double t;
    private Double eDay;
}

Json字符串

{
    "t":12.23,
    "eDay":123.321
}

使用Jackson解析下來,發現只有t有值,而eDay沒有解析到。

原因分析

首先第一反應是Lombok生成的getter和setter也許有問題,於是去掉@Data注解,用IDEA生成getter和setter,再進行反序列化,發現已經可以正常反序列化了。

於是看了下編譯生成的代碼:

public class DemoData{
    private Double t;
    private Double eDay;

    public Double getT() {
        return this.t;
    }

    public Double getEDay() {
        return this.eDay;
    }

    public void setT(final Double t) {
        this.t = t;
    }

    public void setEDay(final Double eDay) {
        this.eDay = eDay;
    }
}

去掉lombok的注解,直接用IDEA生成getter和setter,生成之后是這樣的:

public class DemoData{
    private Double t;
    private Double eDay;

    public Double getT() {
        return t;
    }

    public void setT(Double t) {
        this.t = t;
    }

    public Double geteDay() {
        return eDay;
    }

    public void seteDay(Double eDay) {
        this.eDay = eDay;
    }
}

顯然兩邊的Getter和Setter是不一樣的,那么Jackson是怎么尋找屬性和Setter的呢?

Jackson2在初始化序列器時,對pojo類型對象會收集其屬性信息,屬性包括成員變量及方法,然后屬性名稱和處理過后的方法名稱做為key保存到一個LinkedHashMap中。
收集過程中會調用com.fasterxml.jackson.databind.util.BeanUtil中的legacyManglePropertyName方法用來處理方法名稱,它會將get/set方法前綴,即get或set去掉,並將其后面的連續大寫字符轉換成小寫字符返回。
例如: getNEWString會轉變成newstring返回。你的屬性名稱如果有這樣的"nSmallSellCount",lombok自動生成的get方法就會是這樣的"getNSmallSellCount",處理過后就是這樣的"nsmallSellCount",這與屬性nSmallSellCount並不沖突,可以同時存在於HashMap中。

所以,當Jackson掃描由Lombok生成的POJO時,讀取到setEDay,會把set去掉,拿到EDay,然后轉成eday。由此導致json中的eDay屬性在LinkedHashMap中沒有找到setter方法,反序列化就丟失了字段。

所以原因已經確定了:當使用Lombok修飾的POJO中存在由aAxxx這樣的(單個小寫字母跟着大寫字母)的屬性時,反序列化會丟失這個字段。

如何解決

@JsonProperty

對出問題的字段添加@JsonProperty注解,並設置字段名,就可以正確解析了。

DeLombok

當代碼中出現這樣的字段時,由IDEA生成對應的getter和setter,會自動覆蓋lombok生成的方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM