CARVIEW |
Navigation Menu
-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Summary of dropwizard discussion, specifically the following comment:
When a server receives a payload, attempts to deserialize it, and an exception is raised, there are two possibilities in our eyes:
- A client sent unexpected input and should receive a 4xx response back
- There is a programmatic error (forgot proper annotations, etc) and a 5xx response should be returned
The issue is that both of these situations may throw the same root exception JsonMappingException
, which makes it hard to determine what response should be returned. I propose a new exception: JsonInputMappingException
(name subject to change) or increase usage of InvalidFormatException
Examples
Examples that use just a plain JsonMappingException
where new JsonInputMappingException
or InvalidFormatException
would be used
- Expecting an object, but JSON is false throws a JsonMappingException of "Can not construct instance of foo: no boolean/Boolean-argument constructor/factory method to deserialize from boolean value (false)". This should be a client error because the wrong json type was submitted.
- Expecting a list but given a string throws a JsonMappingException of "Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token"
- Deserializing a DateTime from [1,1,1,1] throws a JsonMappingException of "Unexpected token (VALUE_NUMBER_INT), expected END_ARRAY: Expected array to end."
The Dream
The code needed to determine if it client or server issue:
final JsonMappingException ex = (JsonMappingException) exception;
final Throwable cause = Throwables.getRootCause(ex);
// Exceptions that denote an error on the client side
final boolean clientCause = cause instanceof InvalidFormatException ||
cause instanceof PropertyBindingException ||
cause instanceof JsonInputMappingException;
if (!clientCause) {
LOGGER.error("Unable to serialize or deserialize the specific type", exception);
return Response.serverError().build();
}
or maybe even:
final boolean clientCause = cause instanceof JsonInputMappingException
and have InvalidFormatException
and PropertyBindingException
extend from JsonInputMappingException
, though I do not know if this would be 100% applicable.
Considerations
By creating a new exception that is supposed to represent bad input, exceptions thrown due to bad input in third party libraries that use plain JsonMappingException
, if not changed, can be unexpectedly interpreted as a server/programmatic error. I believe it is best to err on the side of blaming the client/input. Instead, creating a JsonProgrammaticMappingException
may fix this problem.
Would JsonParseException
be a part of JsonInputMappingException
The suggested exception, JsonInputMappingException
, does not apply to serialization. An error on serialization is almost certainly a programmatic error, though I can see a situation where a custom serializer throws on certain input. I understand this to be less of a use case.
Do not create a new exception JsonInputMappingException
or JsonProgrammaticMappingException
, but instead throw instances of InvalidFormatException
for the given examples (more examples may exist, but I'm not aware of them at this point).
Conclusion
Let me know if you need help recreating any examples. I'm torn whether it's best to create a new exception or use InvalidFormatException
more.