Search code examples
javajsonjacksonpojo

Empty JSON response doesn't trigger error in Jackson


I am using Jackson to interpret JSON responses from an API that I am writing. I would like, as a standard throughout my API, to throw errors from the API to the program with something like:

{"errorMessage":"No such username."}

So I want my response processor to first check if the response is just a single errorMessage key, and if so to handle the error, and if not, then to interpret it as whatever response it was expecting from that command.

So here's my code:

public class ProcessingException extends Exception {
    private String errorMessage;
    public ProcessingException(){}

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

}

and then, in my response handler:

@Override
public void useResponse(InputStream in) throws IOException, ProcessingException {
    // turn response into a string
    java.util.Scanner s = new java.util.Scanner(in).useDelimiter("\\A");
    String response = s.hasNext() ? s.next() : "";

    ProcessingException exception;
    try {
        // Attempt to interpret as an exception
        exception = mapper.readValue(response, ProcessingException.class);
    }
    catch(IOException e) {
        // Otherwise interpret it as expected. responseType() is an abstract TypeReference
        // which is filled in by subclasses. useResponse() is also abstract. Each subclass
        // represents a different kind of request.
        Object responseObj = mapper.readValue(response, responseType());
        useResponse(responseObj);
        return;
    }
    // I needed this out of the try/catch clause because listener.errorResponse might
    // actually choose to throw the passed exception to be dealt with by a higher
    // authority.
    if (listener!=null) listener.errorResponse(exception);
}

This works beautifully, except under one circumstance - there are some requests that actually don't need to respond with anything, so they return {}. For some reason, this response completely runs through the exception = mapper.readValue(response, ProcessingException.class); line without triggering an IOException, so the program things that there is an error. But then when it tries to read what the error was, it throws a NullPointerException when trying to read exception.getErrorMessage(), because of course there is no error.

Why is it treating {} as a valid ProcessingException object?


Solution

  • Jackson doesn't have bean validation. But what you can do is to declare constructor as a JsonCreator that will be used to instantiate the new object and check/throw an exception in case if that field is null:

    class ProcessingException  {
        private String errorMessage;
    
        @JsonCreator
        public ProcessingException(@JsonProperty("errorMessage") String errorMessage) {
            if (errorMessage == null) {
                throw new IllegalArgumentException("'errorMessage' can't be null");
            }
            this.errorMessage = errorMessage;
        }
        // getters, setters and other methods
    }