Retrofit access to list withouth reference - android

I have this JSON and when trying to access the list I don't know how to pass the value "Serialized", I don't have any value.
I work on android.
Does anyone know how to access?
Thank you.
[
    {
        "id": “111”,
        "dateStart": "2020-02-26T00:00:00+01:00",
        "dateEnd": "2020-02-26T01:30:00+01:00",
        "sectionId": 0,
        "description": “Test”,
        "comment": “Test comment”,
        "emissionType": “A”,
        "priority": 5,
        "audios": [],
        "idCollection": “1”
    },
    {
        "id": “222”,
        "dateStart": "2020-02-26T00:00:00+01:00",
        "dateEnd": "2020-02-26T01:30:00+01:00",
        "sectionId": 0,
        "description": “Test”,
        "comment": “Test comment”,
        "emissionType": “B”,
        "priority": 5,
        "audios": [],
        "idCollection": “12”
 }
]

public static Gson getGSONBuilder()
{
Gson gson = new GsonBuilder().
registerTypeAdapter(Double.class, new JsonSerializer<Double>()
{
#Override
public JsonElement serialize(Double src, Type typeOfSrc,
JsonSerializationContext context) {
if (src == src.longValue())
return new JsonPrimitive("" + src.longValue());
return new JsonPrimitive("" + src);
}
}).create();
return gson;
}
String responseString=getGSONBuilder().toJson(response.body());//response is Retrofit
response

in retrofit just call the ArrayList> in responce you get all the arraylist data into hashmap with its key and value .
for(int i=0;i<responce.body().size;i++){
arrlist.add(responce.body().get(i))
}

Related

Retrofit 2, GSON and custom deserializer

I've been using Retrofit 2 with some POJO objects for a while now. It's a lovely library and works very well, but it's necessitating some horrendous and messy models that I want to get rid of.
I'll show you... I have the following JSON to peruse:
{
"things": [
{
"thing": {
"id": 823,
"created_at": "2016-02-09T22:55:07.153Z",
"published_at": "2016-02-10T19:23:42.666Z",
"downloads": 16073,
"size": 10716291
}
},
],
"count": 4,
"links": {}
}
Using the POJO Schema generator this creates unnecessary classes that make maintaining code hard to do.
This would create:
Things.java
#SerializedName("things")
#Expose
public List<Things_> things = new ArrayList<>();
Things_.java
#SerializedName("thing")
#Expose
private Thing__ thing;
Things__.java
// Insert normal variables and getter/setters here
I've reduced that down a little as it's just for the idea. In my usage I have of course renamed these classes to make them more managable. But I figured there was a way of simply skipping over Thing and Thing_ and allowing me to just return a list of the actual model data (Thing__) and this two of those classes could be removed and "Thing__" could simple be "Thing".
I was right. Gson allows custom deserialization that lets me achieve this end. I threw together a quick Deserializer and used an appropriate TypeToken
Gson gson = new GsonBuilder()
.registerTypeAdapter(new TypeToken<ArrayList<Thing>>(){}.getType(), new AddonDeserializer())
.create();
List<Thing> model = gson.fromJson(jsonString, new TypeToken<ArrayList<Thing>>(){}.getType());
Sure enough, passing this that exact Json above give me a List of Things that were usable.
Enter Retrofit 2! Having added the registerTypeAdapter() to my Retrofit 2 instance (via my gson instance) I now get an error message:
Expected BEGIN_ARRAY but was BEGIN_OBJECT
This is because, probably, my call is:
#Get("end/of/url/here/{slug}.json")
Call<List<Thing>> getThings(#Path("slug") String slug);
My Json starts with an object ("things") which contains an array of "thing" objects. My deserializer had no issues with this:
public class ThingDeserializer implements JsonDeserializer<List<Thing>> {
#Override
public List<Thing> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonArray array = json.getAsJsonObject().getAsJsonArray("things");
ArrayList<Thing> list = new ArrayList<>();
for (JsonElement anArray : array) {
list.add((Thing) context.deserialize(anArray.getAsJsonObject().get("thing").getAsJsonObject(), Thing.class));
}
return list;
}
}
Anyway, thanks for sticking with this very long question!
What do I need to do differently or how can I manipulate Retrofit to act the same as the Gson Deserializer I wrote? What I have works, but in the interests of learning something new and writing nicer and more maintainable code I want to figure this out. I could just resort to using ResponseBody callbacks and throwing the Json through my Deserializer but there has to be a better method.
Thanks to #JonathanAste I figured it out.
Instead of a Deserializer, I needed a TypeAdapterFactory implementation.
public class ThingTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<T>() {
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}
public T read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("things") && jsonObject.get("things").isJsonArray())
{
jsonElement = jsonObject.get("things");
}
}
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("thing") && jsonObject.get("thing").isJsonObject())
{
jsonElement = jsonObject.get("thing");
}
}
return delegate.fromJsonTree(jsonElement);
}
}.nullSafe();
}
}
And this allows you to then use
#GET("end/of/url/here/{slug}.json")
Call<List<Thing>> getThings(#Path("slug") String slug);
Without issue.

Android Retrotfit modify fields of object after receive

I need to modify some fields of object which I receive from server using Retrofit before I store it internally:
For example, server object model
{
"field1":boolean;
"field2":String
}
app object model:
{
"field1":int=boolean?1:0;
"field2":my prefix + String;
}
Should I write my own parser? Or will parsing using GSON would be enough with some interception before object is stored locally?
Why not changing them after deserilization takes place? It's not that clear what you're trying to do but here is a solution.
(1) Write a deserilizer
public class MyDeserializer implements JsonDeserializer<MyModel> {
...
}
(2) Register type adapter
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyModel.class, MyDeserializer)
.create();
(3) Add it to retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(...)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Alternatively you could just change your field's content after you get your instances.
Using GSON you can write your own JsonDeserializer.
This example shows how translate int in JSON to boolean in your object.
public class BooleanTypeAdapter implements JsonDeserializer<Boolean> {
#Override
public Boolean deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
int code = json.getAsInt();
return code != 0;
}
}
And this:
new GsonBuilder().registerTypeAdapter(boolean.class, new BooleanTypeAdapter()).create();
Hope it helps.

How to pass Arraylist key to server using GSON (Serilized("image"))

I am passing image arrayObject to server using GSON, below is my serializedName and key for this. Hope somebody helps me.
#SerializedName("image")
private ArrayList<MarketPlaceImage> marketPlaceImages;
public ProductReturnFormInput() {
marketPlaceImages = new ArrayList<>();
}
public ArrayList<MarketPlaceImage> getMarketPlaceImages() {
return marketPlaceImages;
}
#SerializedName("image")
private ArrayList<MarketPlaceImage> marketPlaceImages;
When you do this,image is considered as key.

Parse nested object using GsonConverter with Retrofit2

I`m trying to convert the next JSON to object:
{
AccountName:"temnoi",
Parts:{
part-0:{
Name:"HOME",
UptimeSeconds:"2143943",
},
part-1:{
Name:"WORK",
UptimeSeconds:"2276958",
}
}
}
The problem is that Parts isn't an array so I don't have any idea how
to obtain them as List or any other data structure.
For now I have such DTO class
public class Info {
private String AccountName;
private List<Parts> Parts;
}
But obviously program crash as there are no array. I use Retrofit2 with GsonConverter.
Can anyone suggest something to solve this problem?
Unfortunately, as I don't have a lot of time, I came with the next solution.
I replace Retrofit2 by OkHTTP and Gson with built-in JSON parser.
After I get a response with OkHttpClient I manually convert JSON to my object.
JSONObject root = new JSONObject(responseFromServer);
JSONObject parts = root.getJSONObject("Parts");
Iterator<String> jsonPartsIterator = parts.keys();
List<Part> partsList = new ArrayList<>();
while (jsonPartsIterator.hasNext()) {
try{
String key = jsonRootIterator.next();
partsList.add(convertPartJsonToObject(computers.getJSONObject(key)));
} catch(Exception e){
// in case if there will be number '0' return empty List
}
}
Here Part convertPartJsonToObject(JSONObject object) is method to convert part-0, part-1... to object which I need.

How to convert raw JSON response data into an ArrayList of model objects using Spring for Android?

I'm learning spring for android with androidannotations and I'm having trouble casting JSON data received via HTTP Get to my model objects.
I have the following code:
myRestClient.getRestTemplate().getMessageConverters().add(new GsonHttpMessageConverter());
ArrayList liveMatches = myRestClient.getLiveMatchesForUser((long) user_id);
This response is actually just a JSON representation of a list of Match objects.
How can I convert this raw JSON response into an ArrayList<Match> object?
Thanks!
Here is what worked for me.
I created a simple class which was just a wrapper of an ArrayList data structure.
Something like:
public class MatchesListWrapper {
public ArrayList<Match> matches;
public MatchesListWrapper(ArrayList<Match> matches) {
this.matches = matches;
}
public ArrayList<Match> getMatches() {
return matches;
}
public void setMatches(ArrayList<Match> matches) {
this.matches = matches;
}
}

Categories

Resources