摘要:我最終的解決方案是用反序列化,再利用反射工具來對某些數(shù)值進行到的轉(zhuǎn)化。速度快,但是對反序列化的類也有一定要求,而且在反序列化復(fù)雜的時較多阿里云的很多也由于這個原因并未使用。
Problem
在寫Java的Unit Test時,對于Unit Test所期望的值,一般是利用工具從test/resources目錄下將expectResult.json讀取進來并用json序列化工具進行反序列化來獲得Unit Test所期望的結(jié)果,并與測試的實際結(jié)果進行對比。然而若是反序列化所用的類來源于第三方庫(即不能更改任何代碼),會遇到很大的問題。以下以本人對阿里云的StreamRecord類進行反序列化時遇到的問題進行描述:
StreamRecord類的定義如下:
public class StreamRecord { public enum RecordType { /** * PUT類型 * 如果對應(yīng)行已存在,該Record需要覆蓋原有數(shù)據(jù)。 */ PUT, /** * UPDATE類型 * 如果對應(yīng)行已存在,該Record是在原有數(shù)據(jù)上的更新。 */ UPDATE, /** * DELETE類型 * 表明要刪除對應(yīng)的行。 */ DELETE } /** * Record的類型 */ private RecordType recordType; /** * 對應(yīng)行的主鍵 */ private PrimaryKey primaryKey; /** * 對應(yīng)行的時序信息 */ private RecordSequenceInfo sequenceInfo; /** * 該Record包含的屬性列,為RecordColumn類型 */ private Listcolumns; /** * 獲取Record的類型 * @return Record的類型 */ public RecordType getRecordType() { return recordType; } public void setRecordType(RecordType recordType) { this.recordType = recordType; } /** * 獲取對應(yīng)行的主鍵 * @return 對應(yīng)行的主鍵 */ 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的錯誤,經(jīng)過調(diào)查發(fā)現(xiàn)Jackson進行反序列化需要默認(rèn)的構(gòu)造函數(shù)(如果有帶參數(shù)的構(gòu)造函數(shù),還要用@JsonCreator修飾構(gòu)造函數(shù),用@JsonProperty修飾構(gòu)造函數(shù)參數(shù)),而上述類沒有,即使有我們也不能對阿里云等第三方庫進行更改,遂放棄Jackson,轉(zhuǎn)而考慮阿里自己的fastjson。fastjson的確能對該類進行反序列化,但是當(dāng)我仔細(xì)分析反序列化后的對象時,發(fā)現(xiàn)有些深層的字段的值為null,又經(jīng)過一番調(diào)查,了解到fastjson雖然對反序列化的類沒有構(gòu)造函數(shù)的要求,但對字段有要求,反序列化的private字段要有setter方法才能正常的反序列化(或者有一個帶有所有字段參數(shù)的構(gòu)造函數(shù)),若是private字段缺少setter方法,則該字段的值為默認(rèn)值。最后考慮用Google的Gson,Gson沒有上述這些問題,但是若反序列化類有Object類型的字段,而該字段的值為數(shù)值型,則Gson都會轉(zhuǎn)為Double型,比如你有個字段為
private Mapmap;
json文件:
{ "age": 24, "height": 1.81 }
當(dāng)把上述json文件反序列化為map字段時,直覺上會認(rèn)為“age”字段的值的類型應(yīng)該為Integer或Long型,然而Gson這里有點反常,由于map的value為Object類型,并未明確指定具體的數(shù)值類型,它會將key為“age”的字段會變?yōu)镈ouble類型(并不是我們直覺上所期望的Integer或Long型),給后續(xù)編程帶來麻煩。關(guān)于Gson的這個“特性”,可以參考https://github.com/google/gso... 上面的“debate”,比較有趣的“網(wǎng)友懟作者”。
我最終的解決方案是用Gson反序列化,再利用反射工具ReflectionTestUtils.setField來對某些數(shù)值進行Double到Long的轉(zhuǎn)化。
ConclusionJackson 功能強大,但對反序列化的類的要求較高(要有默認(rèn)的constructor)。
Fastjson 速度快,但是對反序列化的類也有一定要求,而且在反序列化復(fù)雜的json時bug較多(阿里云的很多sdk也由于這個原因并未使用fastjson)。
Gson 比較全面,對反序列化的類的要求最低,但是對于Object類型的數(shù)值字段處理不夠友好。
以上實驗所用版本:
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。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/76143.html
摘要:容器內(nèi)文件日志平臺支持的文件存儲是,避免了許多復(fù)雜環(huán)境的處理。以上是數(shù)人云在實踐容器日志系統(tǒng)過程中遇到的問題,更高層次的應(yīng)用包括容器日志分析等,還有待繼續(xù)挖掘和填坑,歡迎大家提出建議,一起交流。 業(yè)務(wù)平臺每天產(chǎn)生大量日志數(shù)據(jù),為了實現(xiàn)數(shù)據(jù)分析,需要將生產(chǎn)服務(wù)器上的所有日志收集后進行大數(shù)據(jù)分析處理,Docker提供了日志驅(qū)動,然而并不能滿足不同場景需求,本次將結(jié)合實例分享日志采集、存儲以...
摘要:一般在存當(dāng)前含有當(dāng)前時間的實體時,只需要配置好數(shù)據(jù)庫的存儲字段即可?;敬a部分循環(huán)的寫法 這幾天初步了解了百度云的后臺架構(gòu)部分,當(dāng)然了,自己了解的僅限于后臺java相關(guān)的部分,先說一下客戶端這邊使用的技術(shù):1、spring boot : 與前端進行直接交互的服務(wù)是用spring來實現(xiàn)的(后臺服務(wù)還需要調(diào)用其他的基礎(chǔ)服務(wù),如redis 數(shù)據(jù)庫服務(wù) 訂單服務(wù) cdn服務(wù) openstac...
摘要:序列化工具類序列化工具的序列化與反序列化使用實現(xiàn)序列化和反序列化反序列化時,必須要有默認(rèn)構(gòu)造函數(shù),否則報錯使用序列化緩存此類分別包含序列化序列化序列化三種序列化方式。 序列化工具類 序列化即將對象序列化為字節(jié)數(shù)組,反序列化就是將字節(jié)數(shù)組恢復(fù)成對象。主要的目的是方便傳輸和存儲。 序列化工具類: public class SerializeUtil { private stati...
摘要:在社區(qū)開發(fā)的一些最新工具集的幫助下,出現(xiàn)了四步流程法,從而進一步加快了開發(fā)效率。兩步流程法傳統(tǒng)上來說,智能合約開發(fā)有兩步開發(fā)流程編碼和測試。四步工作流程法開發(fā)智能合約對于編輯和調(diào)試階段,我建議使用兩種方法和。 摘要:開發(fā)NEO智能合約的典型開發(fā)流程有兩個實際階段:編碼(在IDE中編碼并將源碼編譯為.avm文件)以及測試(在測試網(wǎng)上部署、調(diào)用、檢查結(jié)果)。這個工作流需要編譯和部署來調(diào)試任...
摘要:在社區(qū)開發(fā)的一些最新工具集的幫助下,出現(xiàn)了四步流程法,從而進一步加快了開發(fā)效率。兩步流程法傳統(tǒng)上來說,智能合約開發(fā)有兩步開發(fā)流程編碼和測試。四步工作流程法開發(fā)智能合約對于編輯和調(diào)試階段,我建議使用兩種方法和。 摘要:開發(fā)NEO智能合約的典型開發(fā)流程有兩個實際階段:編碼(在IDE中編碼并將源碼編譯為.avm文件)以及測試(在測試網(wǎng)上部署、調(diào)用、檢查結(jié)果)。這個工作流需要編譯和部署來調(diào)試任...
閱讀 1690·2021-11-22 13:53
閱讀 2939·2021-11-15 18:10
閱讀 2842·2021-09-23 11:21
閱讀 2569·2019-08-30 15:55
閱讀 546·2019-08-30 13:02
閱讀 823·2019-08-29 17:22
閱讀 1779·2019-08-29 13:56
閱讀 3506·2019-08-29 11:31