Reputation: 1569
Here is my sample JSON when a user authenticates successfully
{
"status": "success",
"message": "",
"data": {
"_id": {
"$id": "..."
},
"email": "...",
"name": "...",
"mobile": "...",
"mobile_status": "...",
"email_status": "..."
}
}
And when user credentials are wrong
{
"status": "error",
"message": {
"msg": [
"Login detail incorrect"
]
},
"data": ""
}
Notice the change in datatypes of message
& data
. Using retrofit fit with this I received famously error Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
To resolve this I followed this example to resolve the issue. Which did resolve the OBJECT/ARRAY issue.
I have 3 Models LoginResponse
,MessageResponse
,DataResponse
and this is how I am trying to get access to MessageResponse
& DataResponse
I'm not sure if i can even use 2
Gson messageDeserializer = new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new MessageDeserializer()).create();
Gson dataDeserializer = new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new DataDeserializer()).create();
builder.addConverterFactory(GsonConverterFactory.create(messageDeserializer));
builder.addConverterFactory(GsonConverterFactory.create(dataDeserializer));
I don't think these custom JsonDeserializer
are working the way its supposed to. I'm unable to cast returned response from these JsonDeserializer. The only way I can access them as string only which isn't even a proper JSON formatted string.
Also switching back order of .addConverterFactory sometimes causes a crash when i access LoginResponse
model
Upvotes: 2
Views: 137
Reputation: 527
Do you have access to the network error & response codes?. That way, you may create a switch statement that explicitly defines how you would deserialize ANY response
For example,
Gson switchToDeserialise(int errorCode){
///i assume 200 means correct response. And 404 means there's an errorCode
Gson deserializer = new GsonBuilder().create();
switch(errorCode){
case 200:
return new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new DataDeserializer()).create();
case 404:
return new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new MessageDeserializer()).create();
default:
return deserializer;}}
Note: The above code has not been tested.
=================================== BIT OF A CRASH EDIT REALLY =============================================================================
Based on the conversation we had, and my observation on both the success & error response, i have this un-tested code/suggestion :
//in the retrofit response callback, get the status via JSONObject
JSONObject status = new JSONObject(response.toString()); throws Exception
String statusString = status.optString("status");
//now take the result of the string to a switch statement
Gson switchToDeserialise(String statusString){
///from what you've shown in the success & failure responses, status is either success or error, so...
Gson deserializer = new GsonBuilder().create();
switch(statusString){
case "success":
return new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new DataDeserializer()).create();
case "error":
return new GsonBuilder().setLenient().registerTypeAdapter(LoginResponse.class, new MessageDeserializer()).create();
default:
return deserializer;
}
}
Upvotes: 2