I use Gson inside my projects to deserialize JSON-Strings to Java-Objects. If I do a request, I expect a well-defined response from the Server. The Server will either return the well-defined response I expect, OR it will return me an (also defined) error Object.
To make things clear: suppose I have a simple Object like this:
class Dummy{
private String foo;
private int bar;
}
and an Error Object like this:
class ErrorHolder{
private RequestError error;
}
class RequestError{
private String publicMsg;
private String msg;
}
If I get a Server-response like
{"foo":"Hello World", "bar":3 }
everything works as expected.
But if the response is like this
{"error":{"publicMsg":"Something bad happened", msg:"you forgot requesting some parameter"}}
I’ll get kind of an Dummy object where foo is null and bar is 0! The Gson documentation (fromJson) clearly states that:
throws
JsonSyntaxException – if json is not a valid representation for an
object of type classOfT
so i expected to get an JsonSyntaxException if I try to parse the second response like this:
Dummy dummy = Gson.fromJson(secondResponse, Dummy.class);
because the Json doesn’t represent a Dummy object, but an ErrorHolder Object.
So my question is: Is there a way, that Gson detects a wrong type somehow, and throws me an Exception?
Unfortunately the documentation is slightly misleading there.
It will only throw the exception if your class had a field whose type didn’t match what is in the JSON, and even then it does some crazy things to try and fix it (converting an
intin the JSON to aStringin your class for example). If you had something like aDatefield in your POJO and it encountered anintin the JSON, it’d throw it. Fields that are present in the JSON but not in your POJO are silently ignored, fields that are missing in the JSON but exist in your POJO are set tonull.At present, GSON does not provide a mechanism for any sort of “strict” deserialization where you would have something like a
@Requiredannotation for fields in your POJO.In your case … I’d simply expand my POJO to include an inner error object … something like:
Your other option is to write a custom deserializer that throws the exception if the JSON is the error such as:
Edit to Add: Someone upvoted this recently and re-reading it I thought “Huh, you know, you could do this yourself and it might be handy”.
Here’s a re-usable deserializer and annotation that will do exactly what the OP wanted. The limitation is that if the POJO required a custom deserializer as-is, you’d have to go a little further and either pass in a
Gsonobject in the constructor to deserialize to object itself or move the annotation checking out into a separate method and use it in your deserializer. You could also improve on the exception handling by creating your own exception and pass it to theJsonParseExceptionso it can be detected viagetCause()in the caller.That all said, in the vast majority of cases, this will work:
Output: