GSON deserialize every object (Date, Float, Integer) to string - android

i would like to deserialize string
{
"foo":5,
"bar":"03.10.01"
}
I want to deserialize it to Map which will contain only Strings.
Using sample code gives me Integer in place of "5" and java.Util.Date instead of date String.
Map<Object, Object> map = new HashMap<Object, Object>();
map = (Map<Object, Object>) gson.fromJson(new InputStreamReader(inputStream), map.getClass());
I don't know what will be in JSON, that's why i'm parsing it into Map
#reactivemobile
It's true but what if JSON is like:
As i said, I don't know what will be in JSON, it can look like:
{
"array": [
{
"eggs": 5,
"bb": "03.10.01"
}
],
"foo": 5,
"bar": "03.10.01"
}
Giving this with Map will create Map that contains ArrayList, foo, bar. In ArrayList there will be LinkedTreeMap that will contain "eggs" and "bb".
So your answer is correct, but not in the case where JSON can have dynamic structure.

Use
Map<String, String> map
To force the values to be Strings

Related

Retrofit - Send request body as array or number

I'm using Retrofit 2 and I need to send request body. The problem is somehow the value is converted to string. On the example below, you can see that items and totalPrice which should be array and number respectively are converted to string.
{ cashierId: 'fff7079c-3fc2-453e-99eb-287521feee63',
items: '[{"amount":3,"id":"602a79e3-b4c1-4161-a082-92202f92d1d6","name":"Play Station Portable","price":1500000.0}]',
paymentMethod: 'Debt',
totalPrice: '4500000.0' }
The desired request body is
{ cashierId: 'fff7079c-3fc2-453e-99eb-287521feee63',
items: [{"amount":3,"id":"602a79e3-b4c1-4161-a082-92202f92d1d6","name":"Play Station Portable","price":1500000.0}],
paymentMethod: 'Debt',
totalPrice: 4500000.0 }
Here's the service
#POST("api/sales")
#FormUrlEncoded
Call<Sale> createSale(
#FieldMap Map<String, Object> fields
);
And this is how I call createSale
Map<String, Object> fields = new HashMap<>();
fields.put("cashierId", UUID.fromString("fff7079c-3fc2-453e-99eb-287521feeaaa"));
fields.put("totalPrice", totalPrice);
fields.put("paymentMethod", paymentMethod);
fields.put("items", jsonArray);
Call<Sale> call = retailService.createSale(fields);
Is it possible to send those values as number and array, not as string?
The conversion most certainly happens because you are using #FormUrlEncoded.
According to the documentation:
Field names and values will be UTF-8 encoded before being URI-encoded in accordance to RFC-3986.
A solution would be to use a model class instead of a Map. I see you already have a Sale class. If it looks like something like this:
public class Sale {
String cashierId;
int totalPrice;
String paymentMethod;
ArrayList<SomeObject> items;
}
you can simply do like this:
// in service
#POST("api/sales")
Call<Sale> createSale(#Body Sale sale);
// when doing the call
Sale sale = new Sale();
// set everything in your object
// then
Call<Sale> call = retailService.createSale(sale);

Getting 'unterminated object at' when trying to get value of certain key from JSON

Here's the json structure:
{userModel={name=Mark Kohl Mundi, photo_profile=***}, message=hi, timeStamp=1510326004316, newMsgIndicator=0}
Here's what I'm trying:
for (DataSnapshot childrenSnapshot: dataSnapshot.getChildren()) {
try {
JSONObject reader = new JSONObject(childrenSnapshot.getValue().toString());
String a = reader.getString("newMsgIndicator");
Log.d("A", String.valueOf(a));
} catch (JSONException e) {
e.printStackTrace();
}
}
Here's what I'm getting:
org.json.JSONException: Unterminated object at character 23 of {userModel={name=Mark Kohl Mundi, photo_profile=***}, message=hi, timeStamp=1510326004316, newMsgIndicator=0}
I know the error is because there is no double quotes ("") in the value of the keys.
What I want to know how can I insert double quotes in the json I'm getting.
You don't need to use JSONObject in order to get data from a Firebase database. Firebase database is structured as pair of key and value, which means that every node in the database is a Map. So instead of using JSONObject, i recomand you using this line of code:
Map<String, Object> map = (Map<String, Object>) childrenSnapshot.getValue();
Having this map, you can iterate now to get the data accordingly.
If your reference is pointing on a particular user object (node), to get the actual name, please use the following code:
String name = childrenSnapshot.child("name").getValue(String.class);

JSON: Treat many objects as array of object

I have a JSON Like this
{ "video":{
"video_3745":{ },
"video_3437":{ },
"video_3471":{ },
"video_4114":{ }
}
}
In which every "video_xxxx" is of the SAME type. Is there a way to treat the "video" field as an array of that type? I need to iterate over all the videos, but the API is not sending them in an array, and I don't know how to model a class to receive this JSON without having to manually specify all the field names...
does GSON or LoganSquare have anything to help me out with this?
Try something like this
JSONObject video= json.getJSONObject("video"); // json is the whole response
Iterator x = video.keys();
JSONArray jsonArray = new JSONArray();
while (x.hasNext()){
String key = (String) x.next();
jsonArray.put(video.get(key));
}
You can't treat them as an array, but with the org.json.JSONObject class you can get the list of keys and iterate over them. I believe in GSON the JsonObject.entrySet method will allow something similar.
https://developer.android.com/reference/org/json/JSONObject.html
https://google.github.io/gson/apidocs/com/google/gson/JsonObject.html

How to structure a Map from Json that has duplicate keys

Ok so I have this piece of JSON that I want to parse with Gson. I would like the Strings to be the values and the longs to be the keys.
{"completed_questions":[["String",12345],...]}
The issue is the data type, when I try a Map<String, Long> it parses everything but gives me an error because of the duplicate String keys.
I tried to reverse it thinking Gson would know to switch them around but when I tried Map<Long, String> I got an error about not being able to parse my Strings as Longs.
To get it to work I created a swap map class that takes the Key and Value types and swaps them like so public class SwapMap<K, V> implements Map<K, V> however translating the swapped map actions like put/get/remove seem to be pretty difficult to make work.
What's the best way to parse this with Gson even though the strings aren't unique? (But the numbers are)
JSON doesn't allow identical keys on the same level in a json object. It seems like you are trying to map a json array to a java map.
Based on the following data structure, you would need a list if you want to use the default conversion provided by Gson.
{
"completed_questions": [
[
"String",
12345
],
[
"String",
12345
]
]
}
Here is a quick implementation:
private static void mapToObject() {
String json = "{\"completed_questions\":[[\"String\",12345],[\"String\",123456]]}";
Gson gson = new Gson();
CompletedQuestions questions = gson.fromJson(json, CompletedQuestions.class);
for (List<String> arr : questions.getCompleted_questions()) {
for (String val : arr) {
System.out.print(val + " ");
}
System.out.println();
}
}
public static class CompletedQuestions {
List<List<String>> completed_questions;
public List<List<String>> getCompleted_questions() {
return completed_questions;
}
}
This outputs:
String 12345
String 123456
The thing to note is that I am using a list for mapping purposes which closely resembles the data model provided.
This will require you to do the conversion to long yourself. But the way that json string looks. It seems like you would need to operate on the indices. If you have control over the json structure, I would recommending creating a better model. Other wise you can do something like list.get(0) -> your key list.get(1) -> your value which is the long on the inner list.
So what I did is just made a custom Gson Deserializer that mapped these values to a LongSparseArray<String>, which is the best way to go about it.
This is the relevant parts of the Deserializer:
for (JsonElement array : jsonObject.get("my_key").getAsJsonArray()) {
if (array.getAsJsonArray().size() == 2) {
String value = array.getAsJsonArray().get(VALUE).getAsString();
long key = array.getAsJsonArray().get(KEY).getAsLong();
progress.completedActivities.put(key, value);
}
}
Then I just added it to my Gson creator like so:
#Provides #Singleton Gson provideGson() {
return new GsonBuilder()
.registerTypeAdapter(MyClass.class, new MyClass())
.create();
}

Retrofit parse a json with dynamic keys

I want to use retrofit for my webservices.
I am getting a problem how can I define an object with dynamic Keys.
I am trying to get data for today and tomorrow. Dates will always change.
Here is the json:
{ "2015-11-13": [ ], "2015-11-14": [ ]}
If you are using GSON I guess you can declare the response as JsonObject in your call like this :
#GET("your_api_path")
Call<JsonObject> getDateData();
And then parse it when you get the response
Type mapType = new TypeToken<Map<String, List<YourModel>> >() {}.getType();
Map<String, List<YourModel>> result= gson.fromJson(jsonResponse, mapType);

Categories

Resources