国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java常用json序列化工具的部分局限性

elliott_hu / 3331人閱讀

摘要:我最終的解決方案是用反序列化,再利用反射工具來對某些數值進行到的轉化。速度快,但是對反序列化的類也有一定要求,而且在反序列化復雜的時較多阿里云的很多也由于這個原因并未使用。

Problem

在寫Java的Unit Test時,對于Unit Test所期望的值,一般是利用工具從test/resources目錄下將expectResult.json讀取進來并用json序列化工具進行反序列化來獲得Unit Test所期望的結果,并與測試的實際結果進行對比。然而若是反序列化所用的類來源于第三方庫(即不能更改任何代碼),會遇到很大的問題。以下以本人對阿里云的StreamRecord類進行反序列化時遇到的問題進行描述:

StreamRecord類的定義如下:

public class StreamRecord {

    public enum RecordType {
        /**
         * PUT類型
         * 如果對應行已存在,該Record需要覆蓋原有數據。
         */
        PUT,

        /**
         * UPDATE類型
         * 如果對應行已存在,該Record是在原有數據上的更新。
         */
        UPDATE,

        /**
         * DELETE類型
         * 表明要刪除對應的行。
         */
        DELETE
    }

    /**
     * Record的類型
     */
    private RecordType recordType;

    /**
     * 對應行的主鍵
     */
    private PrimaryKey primaryKey;

    /**
     * 對應行的時序信息
     */
    private RecordSequenceInfo sequenceInfo;

    /**
     * 該Record包含的屬性列,為RecordColumn類型
     */
    private List columns;

    /**
     * 獲取Record的類型
     * @return Record的類型
     */
    public RecordType getRecordType() {
        return recordType;
    }

    public void setRecordType(RecordType recordType) {
        this.recordType = recordType;
    }

    /**
     * 獲取對應行的主鍵
     * @return 對應行的主鍵
     */
    public PrimaryKey getPrimaryKey() {
        return primaryKey;
    }

    public void setPrimaryKey(PrimaryKey primaryKey) {
        this.primaryKey = primaryKey;
    }

    /**
     * 獲取該行的時序信息
     * @return 該行的時序信息
     */
    public RecordSequenceInfo getSequenceInfo() {
        return sequenceInfo;
    }
    public void setSequenceInfo(RecordSequenceInfo sequenceInfo) {
        this.sequenceInfo = sequenceInfo;
    }

    /**
     * 獲取該Record包含的屬性列列表
     * @return 該Record包含的屬性列列表
     */
    public List getColumns() {
        if (columns != null) {
            return columns;
        } else {
            return new ArrayList();
        }
    }

    public void setColumns(List columns) {
        this.columns = columns;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[RecordType:]");
        sb.append(this.recordType);
        sb.append("
[RecordSequenceInfo:]");
        sb.append(this.sequenceInfo);
        sb.append("
[PrimaryKey:]");
        sb.append(this.primaryKey);
        sb.append("
[Columns:]");
        for (RecordColumn column : this.getColumns()) {
            sb.append("(");
            sb.append(column);
            sb.append(")");
        }
        return sb.toString();
    }

}

本工程原先只用Jackson進行序列化和反序列化,但Jackson的ObjectMapper在對此類進行反序列化時,報了No suitable constructor的錯誤,經過調查發現Jackson進行反序列化需要默認的構造函數(如果有帶參數的構造函數,還要用@JsonCreator修飾構造函數,用@JsonProperty修飾構造函數參數),而上述類沒有,即使有我們也不能對阿里云等第三方庫進行更改,遂放棄Jackson,轉而考慮阿里自己的fastjson。fastjson的確能對該類進行反序列化,但是當我仔細分析反序列化后的對象時,發現有些深層的字段的值為null,又經過一番調查,了解到fastjson雖然對反序列化的類沒有構造函數的要求,但對字段有要求,反序列化的private字段要有setter方法才能正常的反序列化(或者有一個帶有所有字段參數的構造函數),若是private字段缺少setter方法,則該字段的值為默認值。最后考慮用Google的Gson,Gson沒有上述這些問題,但是若反序列化類有Object類型的字段,而該字段的值為數值型,則Gson都會轉為Double型,比如你有個字段為

private Map map;

json文件:

{
  "age": 24,
  "height": 1.81
}

當把上述json文件反序列化為map字段時,直覺上會認為“age”字段的值的類型應該為Integer或Long型,然而Gson這里有點反常,由于map的value為Object類型,并未明確指定具體的數值類型,它會將key為“age”的字段會變為Double類型(并不是我們直覺上所期望的Integer或Long型),給后續編程帶來麻煩。關于Gson的這個“特性”,可以參考https://github.com/google/gso... 上面的“debate”,比較有趣的“網友懟作者”。

我最終的解決方案是用Gson反序列化,再利用反射工具ReflectionTestUtils.setField來對某些數值進行Double到Long的轉化。

Conclusion

Jackson 功能強大,但對反序列化的類的要求較高(要有默認的constructor)。

Fastjson 速度快,但是對反序列化的類也有一定要求,而且在反序列化復雜的json時bug較多(阿里云的很多sdk也由于這個原因并未使用fastjson)。

Gson 比較全面,對反序列化的類的要求最低,但是對于Object類型的數值字段處理不夠友好。

以上實驗所用版本:

compile group: "com.google.code.gson", name: "gson", version: "2.8.5"
compile group: "com.alibaba", name: "fastjson", version: "1.2.56"

因此,如果沒有遇到序列化和反序列化第三方庫的model的情況下(即代碼無法更改的情況),首選Jackson,否則選Gson。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76143.html

相關文章

  • 數人云工程師手記 | 容器日志管理實踐

    摘要:容器內文件日志平臺支持的文件存儲是,避免了許多復雜環境的處理。以上是數人云在實踐容器日志系統過程中遇到的問題,更高層次的應用包括容器日志分析等,還有待繼續挖掘和填坑,歡迎大家提出建議,一起交流。 業務平臺每天產生大量日志數據,為了實現數據分析,需要將生產服務器上的所有日志收集后進行大數據分析處理,Docker提供了日志驅動,然而并不能滿足不同場景需求,本次將結合實例分享日志采集、存儲以...

    saucxs 評論0 收藏0
  • 百度java學習筆記

    摘要:一般在存當前含有當前時間的實體時,只需要配置好數據庫的存儲字段即可。基本代碼部分循環的寫法 這幾天初步了解了百度云的后臺架構部分,當然了,自己了解的僅限于后臺java相關的部分,先說一下客戶端這邊使用的技術:1、spring boot : 與前端進行直接交互的服務是用spring來實現的(后臺服務還需要調用其他的基礎服務,如redis 數據庫服務 訂單服務 cdn服務 openstac...

    codeGoogle 評論0 收藏0
  • java常用列化與反列化方法

    摘要:序列化工具類序列化工具的序列化與反序列化使用實現序列化和反序列化反序列化時,必須要有默認構造函數,否則報錯使用序列化緩存此類分別包含序列化序列化序列化三種序列化方式。 序列化工具類 序列化即將對象序列化為字節數組,反序列化就是將字節數組恢復成對象。主要的目的是方便傳輸和存儲。 序列化工具類: public class SerializeUtil { private stati...

    zhkai 評論0 收藏0
  • 開發NEO智能合約步驟流程

    摘要:在社區開發的一些最新工具集的幫助下,出現了四步流程法,從而進一步加快了開發效率。兩步流程法傳統上來說,智能合約開發有兩步開發流程編碼和測試。四步工作流程法開發智能合約對于編輯和調試階段,我建議使用兩種方法和。 摘要:開發NEO智能合約的典型開發流程有兩個實際階段:編碼(在IDE中編碼并將源碼編譯為.avm文件)以及測試(在測試網上部署、調用、檢查結果)。這個工作流需要編譯和部署來調試任...

    I_Am 評論0 收藏0
  • 開發NEO智能合約步驟流程

    摘要:在社區開發的一些最新工具集的幫助下,出現了四步流程法,從而進一步加快了開發效率。兩步流程法傳統上來說,智能合約開發有兩步開發流程編碼和測試。四步工作流程法開發智能合約對于編輯和調試階段,我建議使用兩種方法和。 摘要:開發NEO智能合約的典型開發流程有兩個實際階段:編碼(在IDE中編碼并將源碼編譯為.avm文件)以及測試(在測試網上部署、調用、檢查結果)。這個工作流需要編譯和部署來調試任...

    zhou_you 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<