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

資訊專欄INFORMATION COLUMN

使用 JSONObject 需要注意避免的一個(gè)問題

sutaking / 523人閱讀

摘要:作者介紹鮑協(xié)浩,小米部門,基礎(chǔ)應(yīng)用組通訊錄開發(fā)負(fù)責(zé)人問題現(xiàn)象在業(yè)務(wù)同步的邏輯代碼中,使用到了來解析服務(wù)端的數(shù)據(jù)。

作者介紹:鮑協(xié)浩,小米MIUI部門, MIUI基礎(chǔ)應(yīng)用組通訊錄開發(fā)負(fù)責(zé)人

問題現(xiàn)象

在 Android 業(yè)務(wù)同步的邏輯代碼中,使用到了 JSONObject 來解析服務(wù)端的 JSON 數(shù)據(jù)。同時(shí)本地因?yàn)闃I(yè)務(wù)新增需求的緣故,在本地?cái)?shù)據(jù)庫中使用 JSONObject 緩存了包括水位等同步相關(guān)的信息,其中,水位值是 Long 型。但近期發(fā)現(xiàn)同步過程中下一次同步時(shí),傳遞給服務(wù)器的水位并不是上一次服務(wù)器返回的新水位,而是相差一些。以 301028292893495297L 為例,服務(wù)器返回這個(gè)水位之后,下次客戶端上傳的水位是 301028292893495296L,差值為 -1。

問題排查

通過反復(fù)排查代碼邏輯,發(fā)現(xiàn)水位從服務(wù)端返回到下次請(qǐng)求之間,只經(jīng)過了以下轉(zhuǎn)換:

認(rèn)真閱讀代碼不難發(fā)現(xiàn),Long 型的水位值保存在 JSON 對(duì)象中的時(shí)候轉(zhuǎn)成了 String 型,而在讀取的時(shí)候又當(dāng)作是 Long 型來處理。因此會(huì)有精度缺失的問題,參見如下 JSONObject 的文檔:

由此可見,在讀取 JSON 對(duì)象的某個(gè)值時(shí),如果原先是 String 型,讀取的時(shí)候當(dāng)作是 Long 型,是會(huì)將 String 型通過 Double 進(jìn)行解析的,所以在值超過 2^52 時(shí)會(huì)有精度缺失的問題。于是,遇到的問題就可以解釋了。以下是 Double 的存儲(chǔ)格式規(guī)范:

其中,Double 和 Long 的精度測(cè)試代碼很簡(jiǎn)單(輸入?yún)?shù)可以提供例如 301028292893495297L 這樣超過 2^52 的 long 值,會(huì)發(fā)現(xiàn)其返回值不為 0):

Double 和 Long 的精度測(cè)試代碼很簡(jiǎn)單(輸入?yún)?shù)可以提供例如 301028292893495297L 這樣超過 2^52 的 long 值):

知道了問題的根源,修復(fù)就一目了然了,在水位保存在 JSONObject 對(duì)象中時(shí),應(yīng)該當(dāng)作 Long 型而不是 String 型來保存;亦或者在讀取的時(shí)候也當(dāng)作是 String 型,然后通過 Long.valueOf 等接口進(jìn)行解析。

另外,關(guān)于 JSON 對(duì)象中的值是 Long 型還是 String 型,其實(shí)比較容易被忽略。如果JSON 對(duì)象在使用 String 表示的時(shí)候,該值對(duì)應(yīng)處有引號(hào)就是 String 型??慈缦碌脑囉美鸵荒苛巳涣耍?/p>

類似的問題在網(wǎng)上隨意一搜,其實(shí)有許多人遇坑了,比如這個(gè)。

所以,盡管不能說這個(gè)庫的設(shè)計(jì)是很失敗的,但肯定不算是一個(gè)設(shè)計(jì)良好的庫。因?yàn)槟銦o法直接從 API 名稱看出其內(nèi)在的潛在邏輯,容易導(dǎo)致使用者使用不當(dāng)。因此,經(jīng)驗(yàn)教訓(xùn)就是:使用第三方庫的時(shí)候,能看 API 文檔就看 API 文檔,切不可望文生義。當(dāng)然,這個(gè)問題可能也僅限在 Android 中較老的代碼模塊,畢竟新的代碼都會(huì)使用 GSON 等類庫進(jìn)行 JSON 對(duì)象操作,也就不容易出現(xiàn)這樣的不易發(fā)現(xiàn)的問題了。

當(dāng)然,單就這個(gè)問題來看,其實(shí)是在新增業(yè)務(wù)邏輯的時(shí)候,沒有正確使用 JSONObject 對(duì)象的接口,Long 型的值不應(yīng)當(dāng)看成是 String 型進(jìn)行保存而又當(dāng)成是 Long 型來讀取,如果保存和讀取的接口保持對(duì)應(yīng),也就不會(huì)出現(xiàn)問題了。不管怎么說,該問題的教訓(xùn)是在使用 JSONObject 相關(guān)接口時(shí)要倍加小心謹(jǐn)慎。

備注:Github 上最新的 JSON-Java 庫沒有這個(gè)問題,可以放心使用。

問題解決

知道了問題的根源,修復(fù)就一目了然了,在水位保存在 JSON 對(duì)象中時(shí),應(yīng)該當(dāng)作 Long 型而不是 String 型來保存;或者在讀取的時(shí)候也當(dāng)作是 String 型,然后通過 Long.valueOf 等接口進(jìn)行解析。

問題后話

類似的問題在網(wǎng)上隨意一搜,其實(shí)有許多人遇坑了,比如這個(gè)。所以,盡管不能說這個(gè)庫的設(shè)計(jì)是很失敗的,但肯定不算是一個(gè)設(shè)計(jì)良好的庫。因?yàn)槟銦o法直接從 API 名稱看出內(nèi)在的潛在邏輯,導(dǎo)致使用不當(dāng)。因此,經(jīng)驗(yàn)教訓(xùn)就是:使用第三方庫的時(shí)候,能看 API 文檔就看 API 文檔,切不可望文生義。

當(dāng)然,Github 上最新的 JSON-Java 庫是沒有這個(gè)問題的。

小米開放平臺(tái)重磅推出小米帳號(hào)接入有禮活動(dòng):成功接入小米帳號(hào)即可獲得小米開放平臺(tái)免費(fèi)提供的平臺(tái)資源(小米應(yīng)用商店、小米卡包、小米推送vip、小米帳號(hào)聯(lián)盟等資源),機(jī)會(huì)不容錯(cuò)過,我們期待您的加入!
活動(dòng)報(bào)名地址:http://dev.xiaomi.com/console...

官方QQ交流群:398616987
想要了解更多?
那就關(guān)注我們吧!

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

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

相關(guān)文章

  • poi幾多愁,恰似源碼溫柔

    摘要:拿到值后,創(chuàng)建當(dāng)前單元格,把數(shù)據(jù)填充進(jìn)去。首先判斷當(dāng)前單元格的數(shù)據(jù)是不是數(shù)字型的,如果是數(shù)字型的,在判斷是不是日期類型的,如果是日期類型,再轉(zhuǎn)為日期類型。 導(dǎo)讀 最近,公司在做導(dǎo)入導(dǎo)出的項(xiàng)目,首先想到的是poi的導(dǎo)入和導(dǎo)出。如果每次導(dǎo)入和導(dǎo)出都要重寫的話,那么,實(shí)在是浪費(fèi)時(shí)間和精力。于是,封裝了原生的poi的導(dǎo)入和導(dǎo)出。在封裝的時(shí)候,就會(huì)出現(xiàn)一系列的問題。 在進(jìn)行導(dǎo)入和導(dǎo)出的時(shí)候,我們...

    zhiwei 評(píng)論0 收藏0
  • Java 編程:如何提高性能?(簡(jiǎn)單總結(jié)篇)

    摘要:開發(fā)者在編程中除了要有編程規(guī)范,還要注意性能哦,今天就工作中遇到的一些問題進(jìn)行了一個(gè)簡(jiǎn)單總結(jié),希望攻城獅來批評(píng)指正。 開發(fā)者在編程中除了要有編程規(guī)范,還要注意性能,在 Java 編程中有什么提高性能的好辦法呢? 本文轉(zhuǎn)自國內(nèi) ITOM 行業(yè)領(lǐng)軍企業(yè) OneAPM Cloud Insight(一款能夠優(yōu)雅監(jiān)控多種操作系統(tǒng)、數(shù)據(jù)庫、中間件、云主機(jī)的解決方案)美女工程師陳永梅簡(jiǎn)書。 開發(fā)者在...

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

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

0條評(píng)論

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