成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

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

elliott_hu / 3340人閱讀

摘要:我最終的解決方案是用反序列化,再利用反射工具來(lái)對(duì)某些數(shù)值進(jìn)行到的轉(zhuǎn)化。速度快,但是對(duì)反序列化的類(lèi)也有一定要求,而且在反序列化復(fù)雜的時(shí)較多阿里云的很多也由于這個(gè)原因并未使用。

Problem

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

StreamRecord類(lèi)的定義如下:

public class StreamRecord {

    public enum RecordType {
        /**
         * PUT類(lèi)型
         * 如果對(duì)應(yīng)行已存在,該Record需要覆蓋原有數(shù)據(jù)。
         */
        PUT,

        /**
         * UPDATE類(lèi)型
         * 如果對(duì)應(yīng)行已存在,該Record是在原有數(shù)據(jù)上的更新。
         */
        UPDATE,

        /**
         * DELETE類(lèi)型
         * 表明要?jiǎng)h除對(duì)應(yīng)的行。
         */
        DELETE
    }

    /**
     * Record的類(lèi)型
     */
    private RecordType recordType;

    /**
     * 對(duì)應(yīng)行的主鍵
     */
    private PrimaryKey primaryKey;

    /**
     * 對(duì)應(yīng)行的時(shí)序信息
     */
    private RecordSequenceInfo sequenceInfo;

    /**
     * 該Record包含的屬性列,為RecordColumn類(lèi)型
     */
    private List columns;

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

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

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

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

    /**
     * 獲取該行的時(shí)序信息
     * @return 該行的時(shí)序信息
     */
    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進(jìn)行序列化和反序列化,但Jackson的ObjectMapper在對(duì)此類(lèi)進(jìn)行反序列化時(shí),報(bào)了No suitable constructor的錯(cuò)誤,經(jīng)過(guò)調(diào)查發(fā)現(xiàn)Jackson進(jìn)行反序列化需要默認(rèn)的構(gòu)造函數(shù)(如果有帶參數(shù)的構(gòu)造函數(shù),還要用@JsonCreator修飾構(gòu)造函數(shù),用@JsonProperty修飾構(gòu)造函數(shù)參數(shù)),而上述類(lèi)沒(méi)有,即使有我們也不能對(duì)阿里云等第三方庫(kù)進(jìn)行更改,遂放棄Jackson,轉(zhuǎn)而考慮阿里自己的fastjson。fastjson的確能對(duì)該類(lèi)進(jìn)行反序列化,但是當(dāng)我仔細(xì)分析反序列化后的對(duì)象時(shí),發(fā)現(xiàn)有些深層的字段的值為null,又經(jīng)過(guò)一番調(diào)查,了解到fastjson雖然對(duì)反序列化的類(lèi)沒(méi)有構(gòu)造函數(shù)的要求,但對(duì)字段有要求,反序列化的private字段要有setter方法才能正常的反序列化(或者有一個(gè)帶有所有字段參數(shù)的構(gòu)造函數(shù)),若是private字段缺少setter方法,則該字段的值為默認(rèn)值。最后考慮用Google的Gson,Gson沒(méi)有上述這些問(wèn)題,但是若反序列化類(lèi)有Object類(lèi)型的字段,而該字段的值為數(shù)值型,則Gson都會(huì)轉(zhuǎn)為Double型,比如你有個(gè)字段為

private Map map;

json文件:

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

當(dāng)把上述json文件反序列化為map字段時(shí),直覺(jué)上會(huì)認(rèn)為“age”字段的值的類(lèi)型應(yīng)該為Integer或Long型,然而Gson這里有點(diǎn)反常,由于map的value為Object類(lèi)型,并未明確指定具體的數(shù)值類(lèi)型,它會(huì)將key為“age”的字段會(huì)變?yōu)镈ouble類(lèi)型(并不是我們直覺(jué)上所期望的Integer或Long型),給后續(xù)編程帶來(lái)麻煩。關(guān)于Gson的這個(gè)“特性”,可以參考https://github.com/google/gso... 上面的“debate”,比較有趣的“網(wǎng)友懟作者”。

我最終的解決方案是用Gson反序列化,再利用反射工具ReflectionTestUtils.setField來(lái)對(duì)某些數(shù)值進(jìn)行Double到Long的轉(zhuǎn)化。

Conclusion

Jackson 功能強(qiáng)大,但對(duì)反序列化的類(lèi)的要求較高(要有默認(rèn)的constructor)。

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

Gson 比較全面,對(duì)反序列化的類(lèi)的要求最低,但是對(duì)于Object類(lèi)型的數(shù)值字段處理不夠友好。

以上實(shí)驗(yàn)所用版本:

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

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

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76143.html

相關(guān)文章

  • 數(shù)人云工程師手記 | 容器日志管理實(shí)踐

    摘要:容器內(nèi)文件日志平臺(tái)支持的文件存儲(chǔ)是,避免了許多復(fù)雜環(huán)境的處理。以上是數(shù)人云在實(shí)踐容器日志系統(tǒng)過(guò)程中遇到的問(wèn)題,更高層次的應(yīng)用包括容器日志分析等,還有待繼續(xù)挖掘和填坑,歡迎大家提出建議,一起交流。 業(yè)務(wù)平臺(tái)每天產(chǎn)生大量日志數(shù)據(jù),為了實(shí)現(xiàn)數(shù)據(jù)分析,需要將生產(chǎn)服務(wù)器上的所有日志收集后進(jìn)行大數(shù)據(jù)分析處理,Docker提供了日志驅(qū)動(dòng),然而并不能滿足不同場(chǎng)景需求,本次將結(jié)合實(shí)例分享日志采集、存儲(chǔ)以...

    saucxs 評(píng)論0 收藏0
  • 百度java學(xué)習(xí)筆記

    摘要:一般在存當(dāng)前含有當(dāng)前時(shí)間的實(shí)體時(shí),只需要配置好數(shù)據(jù)庫(kù)的存儲(chǔ)字段即可。基本代碼部分循環(huán)的寫(xiě)法 這幾天初步了解了百度云的后臺(tái)架構(gòu)部分,當(dāng)然了,自己了解的僅限于后臺(tái)java相關(guān)的部分,先說(shuō)一下客戶(hù)端這邊使用的技術(shù):1、spring boot : 與前端進(jìn)行直接交互的服務(wù)是用spring來(lái)實(shí)現(xiàn)的(后臺(tái)服務(wù)還需要調(diào)用其他的基礎(chǔ)服務(wù),如redis 數(shù)據(jù)庫(kù)服務(wù) 訂單服務(wù) cdn服務(wù) openstac...

    codeGoogle 評(píng)論0 收藏0
  • java常用列化與反列化方法

    摘要:序列化工具類(lèi)序列化工具的序列化與反序列化使用實(shí)現(xiàn)序列化和反序列化反序列化時(shí),必須要有默認(rèn)構(gòu)造函數(shù),否則報(bào)錯(cuò)使用序列化緩存此類(lèi)分別包含序列化序列化序列化三種序列化方式。 序列化工具類(lèi) 序列化即將對(duì)象序列化為字節(jié)數(shù)組,反序列化就是將字節(jié)數(shù)組恢復(fù)成對(duì)象。主要的目的是方便傳輸和存儲(chǔ)。 序列化工具類(lèi): public class SerializeUtil { private stati...

    zhkai 評(píng)論0 收藏0
  • 開(kāi)發(fā)NEO智能合約步驟流程

    摘要:在社區(qū)開(kāi)發(fā)的一些最新工具集的幫助下,出現(xiàn)了四步流程法,從而進(jìn)一步加快了開(kāi)發(fā)效率。兩步流程法傳統(tǒng)上來(lái)說(shuō),智能合約開(kāi)發(fā)有兩步開(kāi)發(fā)流程編碼和測(cè)試。四步工作流程法開(kāi)發(fā)智能合約對(duì)于編輯和調(diào)試階段,我建議使用兩種方法和。 摘要:開(kāi)發(fā)NEO智能合約的典型開(kāi)發(fā)流程有兩個(gè)實(shí)際階段:編碼(在IDE中編碼并將源碼編譯為.avm文件)以及測(cè)試(在測(cè)試網(wǎng)上部署、調(diào)用、檢查結(jié)果)。這個(gè)工作流需要編譯和部署來(lái)調(diào)試任...

    I_Am 評(píng)論0 收藏0
  • 開(kāi)發(fā)NEO智能合約步驟流程

    摘要:在社區(qū)開(kāi)發(fā)的一些最新工具集的幫助下,出現(xiàn)了四步流程法,從而進(jìn)一步加快了開(kāi)發(fā)效率。兩步流程法傳統(tǒng)上來(lái)說(shuō),智能合約開(kāi)發(fā)有兩步開(kāi)發(fā)流程編碼和測(cè)試。四步工作流程法開(kāi)發(fā)智能合約對(duì)于編輯和調(diào)試階段,我建議使用兩種方法和。 摘要:開(kāi)發(fā)NEO智能合約的典型開(kāi)發(fā)流程有兩個(gè)實(shí)際階段:編碼(在IDE中編碼并將源碼編譯為.avm文件)以及測(cè)試(在測(cè)試網(wǎng)上部署、調(diào)用、檢查結(jié)果)。這個(gè)工作流需要編譯和部署來(lái)調(diào)試任...

    zhou_you 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<