成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

移動開發 Android 開發工具
在 Android 業務同步的邏輯代碼中,使用到了 JSONObject 來解析服務端的 JSON 數據。同時本地因為業務新增需求的緣故,在本地數據庫中使用 JSONObject 緩存了包括水位等同步相關的信息,其中,水位值是 Long 型。

[[177050]]

鮑協浩,小米MIUI部門, MIUI基礎應用組通訊錄開發負責人。

 

問題現象

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

問題排查

通過反復排查代碼邏輯,發現水位從服務端返回到下次請求之間,只經過了以下轉換:

認真閱讀代碼不難發現,Long 型的水位值保存在 JSON 對象中的時候被轉成了 String 型,而在讀取的時候又當作是 Long 型來處理。所以就會有精度缺失的問題嗎?馬上參考 JSONObject 的文檔:

 

 

 

 

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

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

 

 

 

 

其中,Double 和 Long 的精度測試代碼很簡單(輸入參數可以提供例如 301028292893495297L 這樣超過 2^52 的 long 值,會發現其返回值不為 0):

 

 

 

 

也就是說,在讀取 JSON 對象的某個值時,如果原先是 String 型,讀取的時候當作是 Long 型,是會將 String 型通過 Double 進行解析的,所以在值超過 2^52 時會有精度缺失的問題。

另外,關于 JSON 對象中的值是 Long 型還是 String 型,其實比較容易被忽略。如果JSON 對象在使用 String 表示的時候,該值對應處有引號就是 String 型,否則就是其他類型??慈缦碌?2 個測試用例就一目了然:

Double 和 Long 的精度測試代碼很簡單(輸入參數可以提供例如 301028292893495297L 這樣超過 2^52 的 long 值):

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

另外,關于 JSON 對象中的值是 Long 型還是 String 型,其實比較容易被忽略。如果JSON 對象在使用 String 表示的時候,該值對應處有引號就是 String 型。看如下的試用例就一目了然了:

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

 

 

 

 

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

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

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

 

 

 

 

問題解決

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

問題后話

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

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

【本文是51CTO專欄“小米開放平臺”的原創文章,“小米開放平臺”微信公眾號:xiaomideveloper】

 

責任編輯:龐桂玉 來源: 小米開放平臺
相關推薦

2016-12-26 18:51:34

AndroidJavascriptJSONObject

2012-07-04 14:40:37

Ajax

2024-05-16 15:15:14

2011-07-26 09:19:27

Objective-C 重載

2023-10-04 00:03:00

SQL數據庫

2010-12-31 09:14:36

MongoDB

2015-10-08 10:07:29

游戲開發內存使用

2021-02-24 07:40:38

React Hooks閉包

2011-12-21 09:54:15

項目經理

2010-06-29 15:54:36

UML建模

2020-10-26 14:01:22

Java泛型

2021-02-05 17:35:07

數據高管CIO技術

2013-09-29 10:36:08

VMware虛擬化

2009-04-23 14:30:19

UML建模

2016-09-23 16:09:01

2014-01-26 14:24:25

開源項目

2010-08-09 11:23:24

Flex開發

2021-12-30 06:59:28

方法重寫面試

2010-10-08 09:38:42

mysql修改表

2017-03-17 11:00:08

數字化陳勇Gartner
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本福利视频免费观看 | 欧美中文一区 | 中文字幕99 | 日本手机在线 | 久久久www成人免费无遮挡大片 | 日韩在线视频免费观看 | 精品亚洲一区二区三区四区五区 | 国产99久久精品一区二区300 | 免费黄色的视频 | 欧美区在线 | 国产精品1区2区3区 男女啪啪高潮无遮挡免费动态 | 亚洲一区中文 | 亚洲网在线 | 亚洲女优在线播放 | 国产激情在线看 | 欧美freesex黑人又粗又大 | 免费一级淫片aaa片毛片a级 | 免费一区二区在线观看 | 一级日韩 | 一区二区三区四区电影视频在线观看 | com.色.www在线观看 | 欧美日韩在线视频观看 | 亚洲色图综合 | av先锋资源 | 欧美极品视频在线观看 | 国产精品成人在线 | 在线色网| 中文字幕视频在线观看 | 欧美电影免费观看高清 | 九九久久这里只有精品 | 亚洲精品欧美 | 97精品超碰一区二区三区 | 欧美在线视频一区二区 | 国产在线精品一区二区 | 日韩一区二区在线视频 | 日本在线你懂的 | 国产毛片毛片 | 99精品视频一区二区三区 | 欧美日韩亚洲视频 | 免费国产黄网站在线观看视频 | 伊人春色成人网 |