Bao Xiehao, Xiaomi MIUI department, head of address book development in the MIUI basic application group. Problem phenomenon In the logic code of Android business synchronization, JSONObject is used to parse the JSON data on the server side. At the same time, due to the new business requirements, JSONObject is used in the local database to cache synchronization-related information including water level, where the water level value is Long type. However, it was recently discovered that during the next synchronization process, the water level passed to the server is not the new water level returned by the server last time, but a little different. Take 301028292893495297L as an example. After the server returns this water level, the water level uploaded by the client next time is 301028292893495296L, and the difference is -1. Troubleshooting By repeatedly checking the code logic, we found that the water level only went through the following conversions from the time the server returned to the time the next request was made: If you read the code carefully, you will find that the Long water level value is converted to String when it is saved in the JSON object, and is treated as Long when it is read. So is there a problem of precision loss? Refer to the JSONObject documentation immediately: If you read the code carefully, you will find that the Long water level value is converted to String when it is saved in the JSON object, and is treated as Long when it is read. Therefore, there will be a problem of precision loss, see the following JSONObject documentation: It can be seen that when reading a value of a JSON object, if it is originally a String type, it will be read as a Long type and the String type will be parsed through Double, so there will be a problem of precision loss when the value exceeds 2^52. So, the problem encountered can be explained. The following is the storage format specification of Double: The precision test code for Double and Long is very simple (the input parameter can provide a long value exceeding 2^52 such as 301028292893495297L, and its return value is not 0): That is to say, when reading a value of a JSON object, if it is originally of String type, it will be read as Long type and the String type will be parsed through Double, so there will be a problem of loss of precision when the value exceeds 2^52. In addition, it is easy to overlook whether the value in the JSON object is of Long type or String type. If the JSON object is represented by a String, the value is of String type if there are quotation marks around it, otherwise it is of other types. This is clear from the following two test cases: The precision test code for Double and Long is very simple (the input parameter can provide a long value greater than 2^52 such as 301028292893495297L): Knowing the root cause of the problem, the fix is clear. When the water level is saved in the JSONObject object, it should be saved as a Long type instead of a String type; or when reading it, it should also be treated as a String type and then parsed through interfaces such as Long.valueOf. In addition, it is easy to overlook whether the value in the JSON object is of Long type or String type. If the JSON object is represented by a String, the value is of String type if there are quotation marks around it. The following trial example will make it clear: If you search for similar questions on the Internet, you will find that many people have encountered problems, such as this one. Therefore, although we cannot say that the design of this library is a failure, it is certainly not a well-designed library. Because you cannot directly see the underlying logic of the API name, it is easy to cause users to use it improperly. Therefore, the lesson learned is: when using third-party libraries, read the API documentation if you can, and do not take the words literally. Of course, this problem may only be limited to older code modules in Android. After all, new code will use libraries such as GSON to operate JSON objects, so it is not easy to have such difficult-to-find problems. Of course, looking at this problem alone, it is actually that when adding business logic, the interface of the JSONObject object is not used correctly. The Long value should not be saved as a String type and read as a Long type. If the saving and reading interfaces are kept corresponding, there will be no problem. In any case, the lesson of this problem is to be extra careful when using JSONObject related interfaces. Note: The latest JSON-Java library on Github does not have this problem and can be used without any worries. Problem Solving Knowing the root cause of the problem, the fix is clear. When the water level is saved in the JSON object, it should be saved as a Long type instead of a String type; or it should also be read as a String type and then parsed through interfaces such as Long.valueOf. Afterword If you search for similar problems online, you will find that many people have encountered the same problem, such as this one. Therefore, although we cannot say that the design of this library is a failure, it is definitely not a well-designed library. Because you cannot directly see the underlying logic from the API name, it leads to improper use. Therefore, the lesson is: when using a third-party library, read the API documentation if you can, and do not take it literally. Of course, the popular JSON-Java library on Github does not have this problem. [This article is an original article from the 51CTO column "Xiaomi Open Platform". The WeChat public account of "Xiaomi Open Platform" is: xiaomideveloper] |
<<: Android Development Universal Rounded Corner ImageView
>>: Hortonworks Ted Yu: Tiny LFU, a highly efficient cache admission policy
On the evening of March 24, 2023, a wonderful fai...
An introduction to the clinical diagnosis of depr...
In the early morning of the 10th, my country succ...
"Hurry, eat it while it's hot, it's ...
The latest data from iResearch MUT in April shows...
[[139309]] Thanks to the following habits, I have...
When it comes to promotion , the first step that ...
Search engine mechanism 1. Search mechanism As a ...
2018 has passed so quickly that the New Year’s Da...
Rather than going into a comprehensive guide on h...
Mosquitoes are around every year, how can we avoi...
In the era of mobile Internet, the topic that mar...
The following is the latest traffic ranking of 58...
We often hear various legends about carp leaping ...