自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用JSONObject需要注意避免的一個問題

移動開發(fā) Android
在 Android 業(yè)務(wù)同步的邏輯代碼中,使用到了 JSONObject 來解析服務(wù)端的 JSON 數(shù)據(jù)。同時本地因為業(yè)務(wù)新增需求的緣故,在本地數(shù)據(jù)庫中使用 JSONObject 緩存了包括水位等同步相關(guān)的信息,其中,水位值是 Long 型。但近期發(fā)現(xiàn)同步過程中下一次同步時,傳遞給服務(wù)器的水位并不是上一次服務(wù)器返回的新水位,而是相差一些。

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

[[179904]]

問題現(xiàn)象

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

問題排查

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

 

 

 

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

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

 

 

 

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

 

 

 

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

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

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

 

 

 

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

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

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

備注:Github 上***的 JSON-Java 庫沒有這個問題,可以放心使用。 

 

 

 

問題解決

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

問題后話

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

當然,Github 上***的 JSON-Java 庫是沒有這個問題的。

責任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2016-11-24 15:54:06

androidJSONObject

2012-07-04 14:40:37

Ajax

2023-10-04 00:03:00

SQL數(shù)據(jù)庫

2024-05-16 15:15:14

2015-10-08 10:07:29

游戲開發(fā)內(nèi)存使用

2009-04-23 14:30:19

UML建模

2013-09-29 10:36:08

VMware虛擬化

2021-02-05 17:35:07

數(shù)據(jù)高管CIO技術(shù)

2020-10-26 14:01:22

Java泛型

2014-01-26 14:24:25

開源項目

2011-07-26 09:19:27

Objective-C 重載

2017-03-17 11:00:08

數(shù)字化陳勇Gartner

2021-07-30 09:00:40

鴻蒙HarmonyOS應(yīng)用

2014-12-23 13:50:46

多播組播

2016-12-16 14:57:19

2013-12-19 13:25:40

InnoDB數(shù)據(jù)庫

2024-03-21 15:01:44

2019-06-23 16:02:12

Kubernetes集群節(jié)點高并發(fā)

2009-08-10 15:56:35

802局域網(wǎng)網(wǎng)橋兼容性

2023-07-27 18:39:20

低代碼開發(fā)編碼
點贊
收藏

51CTO技術(shù)棧公眾號