Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to distinguish long and double-values when deserializing with moshi?

Tags:

java

json

moshi

My goal is to synchronize abitrary rows of data by using the JSON-Format. As I do not know the exact scheme for the rows (it is a general sync method), my datamodel apparently has to rely on "Object". So in Java I will have an array of Map<String,Object> to be synchronized with the server.

Translating such a row into JSON would give something like

{{"string":"stringvalue"},{"double1":1234.567},{"double2":1234.0},{"long":1234}}

so far, so good - no problem with moshi - everything works as expected.

Now the Problem: When I try to deserialize that JSON with moshi, I get back a double-value for the "long" member. Moshi converts all numbers to Doubles. But unfortunately not all numbers can be safely converted to doubles. Very big integers (aka longs) have a problem with the limited precision of doubles. And rounding-effects also might exist.

I opened an issue with moshi, but unfortunately that was closed. Maybe I wasn't clear enough. (Issue 192)

JSON has no concept of integer - only numbers and Strings. But the subtle detail from "double2" from the example above might lead to a solution for my problem:
If a number does not contain a decimal-point, it is an integer and should be converted to a long.

As longs can not be losslessly converted to doubles, I need a method to intercept the parser before the value is converted to double. But how to do that?

Moshi has this handy concept of JsonAdapters - but unfortunately I currently do not see how I can use them in this case:
The input-type of such an JsonAdapter would have to be Object because I can not cast a generated double to long. So I have to intercept the parser before he converts any value.
But how to return more than one type from there? (I would have to return String, Double or Long from there - or if I can limit the inputs to only numbers I would at least have to return Longs or Doubles.)

(My backend is written in PHP and automatically produces the desired output: Integers are written without a decimal-point.)

like image 603
Sqrt-1764 Avatar asked Oct 19 '22 01:10

Sqrt-1764


1 Answers

I am afraid it's not possible without changing Moshi source code. The JSON string source passes through JsonReader which converts all numbers to double. I could not find a way how to alter this behavior since all subclasses are package-protected.

like image 52
Lukas Avatar answered Nov 01 '22 08:11

Lukas