How are doubles converted to string with retrofit2? - java

We have the following method declaration in our api:
Call<WeatherResult> getWeatherPredictions(#Query("lat") double latitude, #Query("lon") double longitude);
Now the API that we consume is rather "simple" as it just sends back 400s when its not happy with the given latitude or longitude. They could easily "patch" the values on their end but they won't.
My question now is, does anybody know how doubles are converted by retrofit2? I quickly looked at the source code but kind not find anything there.

My question now is, does anybody know how doubles are converted by
retrofit2?
They are using String#valueOf(Object). Query is an interface. You can find it here. The documentation states:
Values are converted to strings using {#link String#valueOf(Object)}
and then URL encoded.

Related

Java: Org.JSON Library writes inconsistent datatypes [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I read and write a set of numerical values to a JSON file - they are all the 'double' datatype in Java. An example is the following:
double length = 22.4
double height = 13.1
double width = 17.9
double mass = 15.0
A JSONArray, 'objects', will then contain JSONObjects, each of which will contain the above measurements. Using the same values as above, it will look something like this (pay attention ot the datatypes):
"objects" :
[
{
"length" : 22.4,
"width" : 17.9,
"height" : 13.1,
"mass" : 15
}
]
The first issue posed by such a document is the fact that reading 'length', 'width' and 'height' will return a datatype 'BigDecimal' which seems unnormal for the org.json library which to my knowledge only returns double and integer. This is a problem because I need to convert the 'BigDecimal' values back to double although I wrote the JSON object using standard java double values. Additionally, the org.json library seems to convert any 'double' datatypes to integers when read (notice how mass is '15' and not '15.0'? This is a problem because as you can probably tell, the numerical value of "mass" may be different for another JSONObject (and thus indeed be a double). You can probably imagine the hell, that is iterating through this JSONArray when random values are an integer...
In summary, my problem is the fact that reading JSON files with the org.json library means that numerical values are only returned as doubles or BigDecimals. My question is if I can specify what datatype I would like org.json to write? All I want, is to read and write all my numerical values as a double - I don't want org.json to choose which datatype it will write to the JSON file.
My ideas were the following:
Writing everything as a string and converting back to double when reading
My attempts to solve this that haven't worked or are redundant to me:
Using the valueOf method to change between datatypes
Writing 9999 conditions to find the right instances to convert back to double (which sucks)
Using doubleValue() method
All I want, is to read and write all my numerical values as a double - I don't want org.json to choose which datatype it will write to the JSON file.
For what it is worth, the JSON library is not choosing a data type. It is choosing a character based representation to express a value. And there is some logical justification for it doing what it is doing. JSON is (or at least originated as) a subset of Javascript. In Javascript, integer and floating point are not distinct types. There is just one primitive data type for all numbers in Javascript.
I don't think that this can be solved using the org.json code. The stripping of trailing zeros after a decimal point happens in the static JSONObject::numberToString. Since it is a static method, you can't override it in a subclass.
(Take a look at the source code.)
My suggestions:
Work with the current behavior. For example, your code could be written know which fields are supposed to have floating point values, and use doubleValue() to retrieve their values.
Find an alternative JSON library that doesn't do this. (Based on my reading of the code, I think Jackson would be OK. I haven't checked any other libraries ...)
You could create your own private fork of the org.json library and modify it, but then you would be stuck with the overhead of maintaining that fork indefinitely.
I think that 3 is a bad idea. I have only included it for completeness.

RecyclerView Adapter Map instead of Arraylist [duplicate]

Edit: Figured it out, check my posted answer if you're having similar issues.
I know there are several questions about this issue, but none of their solutions are working for me.
In my model class I have made sure to use List instead of Arraylist to avoid Firebase issues, but am still getting this error. It's a lot of code but most questions ask for all the code so I'll post it all.
TemplateModelClass.java
//
I've used this basic model successfully many times. For the
HashMaps<String, List<String>>,
the String is an incremented Integer converted to String. The List's are just Strings in a List. Here's some sample JSON from Firebase:
//
Formatted that as best as I could. If you need a picture of it let me know and I'll get a screenshot
And am getting this error, as stated in the title:
com.google.firebase.database.DatabaseException: Expected a Map while deserializing, but got a class java.util.ArrayList
The most upvoted question about this seems to have something to do with a problem using an integer as a key, but I think I've avoided that by always using an integer converted to a string. It may be interpreting it strangely, so I'll try some more stuff in the meantime. Thanks for reading!
Alright, figured it out. If anyone reading this has this problem and are using incremented ints/longs/whatever that get converted to strings, you must add some characters to the converted int. Firebase apparently converts these keys back into non-Strings if it can be converted.
For example, if you do something like this:
int inc = 0;
inc++; // 1
map.put(String.valueOf(inc), someList);
Firebase interprets that key as 1 instead of "1".
So, to force Fb to intepret as a string, do something like this:
int inc = 0;
inc++; // 1
map.put(String.valueOf(inc) + "_key", someList);
And everything works out perfectly. Obviously if you also need to read those Strings back to ints, just split the string with "[_]" and you're good to go.
The main issue is that you are using a List instead of a Map. As your error said, while deserializing it is expectig a Map but is found an ArrayList.
So in order to solve this problem youd need to change all the lists in your model with maps like this:
private Map<String, Object> mMapOne;
After changing all those fileds like this, you need also to change your public setters and getters.
Hope it helps.

How to distinguish long and double-values when deserializing with 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.)
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.

java.math.BigDecimal.scale() equivalent for double

I've got a matrix of values like the one below that I need to scale. I've been looking around for an inbuilt function if there is one that could do this for me. I haven't found one & so have ended up writing code to do the scaling using the below formula
scaledMatrix = (Matrix - MeanMatrix)/Standard Deviation
This code is a bit buggy & I'm working on correcting it. While I do that, I happened to bump on java.math.BigDecimal.scale() & did look up an equivalent for double as the matrix I have is double type numbers
If someone could please help me with details on
1) If there is an inbuilt function that accepts matrix of values & returns me the scaled matrix
2) `java.math.BigDecimal.scale()` equivalent for `double` type data
Any help would be much appreciated please.
The BigDecimal.scale() method does not do what you seem to think it is doing. A BigDecimal value is stored as a * 10^b (where ^ denotes exponentiation). The BigDecimal.scale() method basically returns the b part of that.
I do not know of a similar method for double values, nor do I know of a method which performs the function you need. Since you put apache-commons in the tags, I suggest you look into Apache Commons's extensive statistical library.

Convert GeoDB Geocoordinates to Lat/Lon and do an area search

I have a Database with GeoCoordinates of every Zipcode in a Decimal form (e.g. 5099755, 928690)
I want to do an area search based on these values, but in the formula that I'v found, I should pass the Lat and Lon values as Double.
How can I convert these "decimal" values to "double" values?
If GeoPoints is the GeoCoordinates variable
double lat = GeoPoints.getLattitude(); or double lat = GeoPoints.getLattitudeE6;
double lon = GeoPoints.getLongitude(); or double lat = GeoPoints.getLongitudeE6;
I think we need to know what sort of coordinate system your numbers are in - they look like they might be UTM (universal transverse mercator), but if so, there should also be a 'Zone' parameter (e.g. 55H). This document describes how to convert from UTM to DMS (and provides parameters for the various geographic datums) and also provides Javascript which you should be able to convert into Java pretty easily.
Also, have a look at this stackoverflow post, which talks about java packages which can do coordinate system conversion.
Then again, maybe your code wants data in exactly the format they're already in, in which case all you need to do is cast your decimals to doubles.

Categories

Resources