I parse server JSON response with GSON library. Backend guys sometimes tell me: "We can't specify variable type in JSON for some reason" (old php, they don't know how to do it and so on and so forth). GSON likes strong typing in its object model. So I can't parse Object as String.
GSON wait for:
{
"service":{
"description":null,
"name":"Base",
"id":"4c7a90410529"
}
}
But it gets (empty data):
"service": ""
And I get
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1396
What is the best practice to parse such response?
Another question: How can I build object, it can recognize Integer variable which returned from time to time as Integer or as String? The same server side issue.
"data": "1"
or
"data": 1
I know - we should use specific types in Java. But sometime it is worth to make concessions,
Thanks
EDIT:
My solution based on Java Developer's answer.
ServiceDeserializer class deserialize every object depending on its internal value.
public class ServiceDeserializer implements JsonDeserializer<ServiceState>{
@Override
public ServiceState deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String name = "";
String uuid = "";
String description = "";
if (json.isJsonObject()) {
JsonObject obj = json.getAsJsonObject();
if (!obj.get("name").isJsonNull()) {
name = obj.get("name").getAsString();
}
if (!obj.get("uuid").isJsonNull()) {
uuid = obj.get("uuid").getAsString();
}
if (!obj.get("description").isJsonNull()) {
description = obj.get("description").getAsString();
}
}
return new ServiceState(name, uuid, description);
}
}
And my GSON constructor with type adapter for ServiceState.
Gson gson = new GsonBuilder()
.registerTypeAdapter(ServiceState.class, new ServiceDeserializer())
.create();
Your json is invalid and any Json parser wouldn't be able to parse a syntactically incorrect json:
should be encapsulated in curly braces as mentioned here:
If you want to stick with strictly
gson
you can provide a custom deserializer. Since we know thatservice
is either a property of the basejson
string or embedded within some otherproperty
, we can use the deserializer to step-wise parse out the offending components and handle them accordingly.The custom deserializer would be called as follows:
I typed all this up so if I missed some syntax my apologies.
A json structure is enclosed within
{}
. Your response seems to be missing that. You can manually append{
and}
at the beginning and end of the string to make it into a valid json structure.Once this is done, you can use Gson to parse your json response normally.
Use a good enough Json parser. That's more than enough. And try to have a class representing the exact same Structure as the response to avoid parsing the json responses level by level, manually.
You need to scrape the JSON response before trying to deserialize it into your
Response
Java object. You can make use of Java org.json parser to verify thatservice
object actually exists and fix it otherwise.Output :
Secondly,
Gson
is smart enough to do simple conversions likeString
toInteger
etc. So, deserializing such JSON properties shouldn't give you any troubles.