Reputation: 159
I'm sending an HTTP request using Retrofit 2, I've done everything regularly, however, the situation is "not standard". I have a problem that one of the objects to receive in the response class is once sent as an object and in the other as a list. So I don't know whether to initialize it in the response class as an object or as an array.
Here is my full JSON response:
{
"data": [
{
"name": "John",
"surname": "Smith",
"nicname": "Joe",
"age": "32",
"description": "Example",
"state": "Nevada",
"city": "Las Vegas",
"job": "Security",
"adress": "Some adress 1",
"postcode": "412421",
"details": {
"intro": {
"title": "Mr.",
"married": "No",
"children": "2"
},
"rest": {
"pitctures":"24",
"chats": "7",
"lastChat": "12-01-2016",
"lastVisited": "07-04-2017",
}
}
},
{
"name": "John",
"surname": "Smith",
"nicname": "Joe",
"age": "32",
"description": "Example",
"state": "Nevada",
"city": "Las Vegas",
"job": "Security",
"adress": "Some adress 1",
"postcode": "412421",
"details": {
"intro": {
"title": "Mr.",
"married": "No",
"children": "No"
},
"rest": []
}
}
],
"errors": false,
"update_notifications": {
"message": [],
"friend_request": [],
"code": "IzS0hivN1cyHBdygpeWv"
}
}
Details.java class:
public class Details {
@SerializedName("intro")
@Expose
private Intro intro;
@SerializedName("rest")
@Expose
private Rest restObject;
private ArrayList<Rest> restList;
public Details(Intro intro, Rest restObject) {
this.intro = intro;
this.restObject = restObject;
}
public Details(Intro intro, ArrayList<Rest> restList) {
this.intro = intro;
this.restList = restList;
}
public Intro getIntro() {
return intro;
}
public void setIntro(Intro intro) {
this.intro = intro;
}
public Rest getRestObject() {
return restObject;
}
public void setRestObject(Rest restObject) {
this.restObject = restObject;
}
public ArrayList<Rest> getRestList() {
return restList;
}
public void setRestList(ArrayList<Rest> restList) {
this.restList = restList;
}
}
And here is my CustomDeserializer.java (rest array neeed to be empty, maybe that's a problem) based on @Farid's answer:
public class CustomDeserializer implements JsonDeserializer<Details> {
@Override
public Details deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject detailsObject = json.getAsJsonObject().get("details").getAsJsonObject();
Details details;
JsonObject introObject = detailsObject.get("intro").getAsJsonObject();
String title = introObject.get("title").getAsString();
String married = introObject.get("married").getAsString();
String children = introObject.get("children").getAsString();
try {
JsonObject restObject = detailsObject.get("rest").getAsJsonObject();
String pitctures = restObject.get("pitctures ").getAsString();
String chats = restObject.get("chats ").getAsString();
String lastChat = restObject.get("lastChat ").getAsString();
String lastVisited = restObject.get("lastVisited ").getAsString();
details = new Details(new Intro(title, married, children),
new Rest(pitctures, chats, lastChat, lastVisited));
}catch (IllegalStateException e){
JsonArray restArray = detailsObject.get("rest").getAsJsonArray();
ArrayList<Rest> restList = new ArrayList<>();
details = new Details(new Intro(title, married, children), restList);
}
return details;
}
}
In MainActivity based on @Farid's answer:
Gson gsonConverter = new GsonBuilder().registerTypeAdapter(Details.class, new CustomDeserializer()).create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(myUrl)
.addConverterFactory(GsonConverterFactory.create(gsonConverter))
.build();
service1 = retrofit.create(MyAPI.class);
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
progressDialog.setMessage("Please wait!");
progressDialog.show();
final MyRequest myRequest = new MyRequest();
myRequest.setPin(pin);
final Call<MyResponse> myResponseCall = service1.get (code, myRequest);
myResponseCall.enqueue(new Callback<MyResponse>() {
@Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
}
});
Upvotes: 0
Views: 386
Reputation: 2562
It's possible. You'll have to create a custom Deserializer. As you can see there is JsonDeserializer<Details>
whose type parameter is Details
that means any time GSON tries to deserialize Details
object, it will call CustomDeserializer
to deserialize it. Anything inside Details
object should be deserialized manually as seen in the CustomDeserializer
class whereas all other types outside Details
class (e.g. Class, String, int) will be handled by GSON seamlessly
CustomDeserializer.java
public class CustomDeserializer implements JsonDeserializer<Details> {
@Override
public Details deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject detailsObject = json.getAsJsonObject();
Details details;
Intro intro = new Intro(detailsObject.get("intro").getAsJsonObject().get("example").getAsString());
try {
JsonObject restObject = detailsObject.get("rest").getAsJsonObject();
String example = restObject.get("example").getAsString();
details = new Details(intro, new Rest(example));
}catch (IllegalStateException e){ // In case rest is ArrayList
JsonArray restArray = detailsObject.get("rest").getAsJsonArray();
ArrayList<Rest> resList = new ArrayList<>();
for (JsonElement element: restArray){
JsonObject restObject = element.getAsJsonObject();
String example = restObject.get("example").getAsString();
resList.add(new Rest(example));
}
details = new Details(intro, resList);
}
return details;
}
}
Then you have to register CustomDeserializer
as TypeAdapter
as below:
Gson gsonConverter = GsonBuilder().registerTypeAdapter(Details::class.java,
CustomDeserializer()).create();
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gsonConverter))
///Rest of Retrofit builder code
If you want to know more about custom deserialization, search for "gson deserialization" and find a tutorial that appeals to you most.
Response.java
public class Response {
private List<DataItem> data = null;
private Boolean errors;
private String example;
public List<DataItem> getData() {
return data;
}
public void setData(List<DataItem> data) {
this.data = data;
}
public Boolean getErrors() {
return errors;
}
public void setErrors(Boolean errors) {
this.errors = errors;
}
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
}
Data.java
public class DataItem {
private String example;
private Details details;
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
public Details getDetails() {
return details;
}
public void setDetails(Details details) {
this.details = details;
}
}
Details.java
public class Details {
private Intro intro;
private Rest restObject;
private ArrayList<Rest> restList;
public Details(Intro intro, ArrayList<Rest> restList) {
this.intro = intro;
this.restList = restList;
}
public Details(Intro intro, Rest restObject) {
this.intro = intro;
this.restObject = restObject;
}
public Rest getRestObject() {
return restObject;
}
public ArrayList<Rest> getRestList() {
return restList;
}
public Intro getIntro() {
return intro;
}
public void setIntro(Intro intro) {
this.intro = intro;
}
}
Intro.java
public class Intro {
public Intro(String example) {
this.example = example;
}
private String example;
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
}
Rest.java
public class Rest {
private String example;
public Rest(String example) {
this.example = example;
}
public String getExample() {
return example;
}
}
Upvotes: 1