AndroidTank
AndroidTank

Reputation: 354

How to valid incoming JSON and check for missing properties? [Jackson,Jersey]

I'm using Jackson 2.7.0. and latest Jersey for JSON on REST API that handles DB communication with Hibernate 5+.

I don't know how to verify incoming JSON if there are any missing properties in it. It is impossible to perform checking on primitive type if they are null. But also i would like to use primitive types because of performance hit. What is best practice to handle such problem?

When I receive JSON like below, everything is ok:

{"vehicle":{"id":1},"distance":1000,"quantity":2000} 

But when i receive JSON like:

{"vehicle":{"id":1},"quantity":2000}

then distance is set to default value 0.

My entity look like

public class Consumption{

private int id;
private double quantity;
private double distance;

@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public Consumption(
        @JsonProperty(value = "quantity", required = true)double quantity, 
        @JsonProperty(value = "distance", required = true)double distance,
        @JsonProperty(value = "vehicle", required = false)Vehicle vehicle) {...

And REST method:

@POST
@Path("/setConsumption/")
public Response setConsumption(@Valid Consumption consum){...

Tried solution #1

I have already tried, to set all values to default value of -1 and then check if it is less then 0, but problem remains with boolean values, where i can not set it to the "neutral" value.

How do you usually handle such problem with missing property in JSON?

Tried solution #2

As you can see i have used @JsonProperty(value = "quantity", required = true) in constructor. This is new feature for Jackson 2.7.0.+, that handles this type of problem. But i get this exception:

Missing required creator property 'distance' (index 1) at 
[Source:org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@1b72cb6; line: 1, column: 181]

This exception is returned to user BEFORE JSON reaches my code. So i can not catch it as exception. I have custom responses with httpCode and errorMessage to inform user about them. Problem is that i don't know how to catch this exception and return it to user in my custom form with my text.

Searching for solution

I have either to catch exception of new Jackson feature or try to validate JSON. But i would not like to use class Integer instead of primitive data type int, because of performance. If it is possible not to write custom JSON deserializer for all 60+ classes i have in project.

If any other solution then Jackson or Jersey supports this types of handling of missing properties, feel free to comment.

TDLR - how to check if variable of primitive data type (int, double, boolean,...) was in incoming JSON or not, without manually writting deserializers for each of 60+ classes in project. Java does not allow to check those types with null.

Suggestion #1

Trying to register an ExceptionMapper for JsonMappingException and see if it overrides the one already registered by Jersey.

My code (still getting default "Missing property ..." exception - problem not solved):

@Provider
public class JacksonNoPropertyMapper implements ExceptionMapper<JsonMappingException> {
    @Override
    public Response toResponse(JsonMappingException e) {

    return Response.status(999).entity("OVERRIDE TEST").type(MediaType.APPLICATION_JSON).build();
}

}

Upvotes: 4

Views: 5608

Answers (1)

DominicEU
DominicEU

Reputation: 3631

The easiest way for you to approach this would be to use the Object counter parts on fields that are optional, it shouldn't affect you too much performance wise, and would allow you to null check the fields.

public class Consumption {

private int id;
private double quantity;
private Double distance;

public boolean isDistanceSet() {
    return distance != null;
}

Upvotes: 2

Related Questions