5

I've developed a Java REST service using JSON-B to map the incoming payload to a POJO.

Now what I'd like to do is to validate the incoming payload, possibly against a JSON schema, but I haven't been able to find anything in this sense so far...

Is it possible to override the default JSON-B mapping process, hence catching any mapping exception and handling it on my own?

Jens Piegsa
  • 7,399
  • 5
  • 58
  • 106
voccoeisuoi
  • 325
  • 4
  • 11

3 Answers3

1

To accomplish this you could register your own JAX-RS provider that does the JSON (de)serialization and handle any errors there.

For example:

@Consumes({ "*/*" })
@Provider
public class JsonBProvider implements MessageBodyReader<Object> {

    private static final Jsonb jsonb = JsonbBuilder.create();

    @Override
    public boolean isReadable(Class<?> type, Type genericType, 
                              Annotation[] annotations, 
                              MediaType mediaType) {
        return true;
    }

    @Override
    public Object readFrom(Class<Object> clazz, Type genericType, Annotation[] annotations,
                           MediaType mediaType, MultivaluedMap<String, String> httpHeaders, 
                           InputStream entityStream) 
                  throws IOException, WebApplicationException {
        try {
            return this.jsonb.fromJson(entityStream, clazz);
        } catch (Exception e) {
            // Do your custom handling here
        }
    }
}

This will override the deserialization that occurs through JAX-RS and JSON-B.

NOTE: If you want to do the same thing for serialization as well, you can implement MessageBodyWriter<Object> in a similar fashion.

Andy Guibert
  • 41,446
  • 8
  • 38
  • 61
0

Validation and deserialization are separate concerns, so I would tie them together only if I really need to, e.g. if you really must use JSON Schemas. But if you are free to choose your own way to declare the constraints, I recommend bean validation, e.g. a JAX-RS resource like this (note the @Valid annotation):

@Path("ping")
public class PingBoundary {
    @POST
    public String ping(@NotNull @Valid Person addressee) {
        return "Hi " + addressee.getName() + "!";
    }
}

And a payload class like this (using the lombok @Data annotation):

@Data
public class Person {
    private String name;
    @Min(0)
    private short age;
}

Passing an invalid age of -2 gives you a 400 Bad Request with a helpful response body:

{
    "classViolations": [],
    "exception": null,
    "fieldViolations": [],
    "parameterViolations": [
        {
            "constraintType": "PARAMETER",
            "message": "must be greater than or equal to 0",
            "path": "ping.addressee.age",
            "value": "-2"
        }
    ],
    "propertyViolations": [],
    "returnValueViolations": []
}

Note that you should pass -parameters to the compiler, or the path would be ping.arg0.age.

rü-
  • 2,129
  • 17
  • 37
0

If you really stick to JSON Schema, validating JSON document while deserializing it can be achieved by using Justify. There is a Binding example which shows how to use the JSON validator with JSON-B. I hope the example code may help you.

Full Disclosure: I am the author of the library.

leadpony
  • 214
  • 2
  • 4