3

I would like the Jackson JSON serializer to fail if it encounters required attributes that are null.

I know I can tell it to omit null fields (mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)). However, in addition I'd like to declare

@NotNull // BeanValidation
private String foo;

or

@JsonProperty(required = true) // Jackson databinding
private String foo;

and have the serializer fail if such fields are null.

Marcel Stör
  • 22,695
  • 19
  • 92
  • 198

1 Answers1

2

I don't see any annotation or configuration option for that. You can use hibernate-validator to validate an object before serializing. Since you don't want to add custom annotations you can modify the default serializer by having your objects validated before serialization.

First create a custom serializer that takes another one as constructor argument and uses hibernate validator to validate objects and throw an exception.

class ValidatingSerializer extends JsonSerializer<Object> {
    private final JsonSerializer<Object> defaultSerializer;
    private final Validator validator;

    ValidatingSerializer(final JsonSerializer<Object> defaultSerializer) {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        this.validator = factory.getValidator();
        this.defaultSerializer = defaultSerializer;
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider)
            throws IOException {
        if (!validator.validate(value).isEmpty()) {
            throw new IOException("Null value encountered");
        }
        defaultSerializer.serialize(value, gen, provider);
    }
}

Then create serializer modifier that will use this serializer:

class ValidatingSerializerModifier extends BeanSerializerModifier {
    @Override
    public JsonSerializer<?> modifySerializer(SerializationConfig config,
             BeanDescription beanDesc, JsonSerializer<?> serializer) {
        return new ValidatingSerializer((JsonSerializer<Object>) serializer);
    }
}

Finally register this on you ObjectMapper with a SimpleModule:

SimpleModule module = new SimpleModule();
module.setSerializerModifier(new ValidatingSerializerModifier());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);

This will now be used and exceptions will be thrown whenever validation fails for fields annotated with standard validation annotations:

@NotNull // BeanValidation
private String foo;
Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
  • Cool, thanks for all the effort that went into this revised answer. I'd upvote it twice if I could. – Marcel Stör Aug 11 '17 at 05:55
  • Btw the reason for this question stems from https://stackoverflow.com/q/45575493/131929. In short, if the OpenAPI definition of your REST API says that JSON property A#foo be mandatory the consumer/client may expect that a request fails (i.e. you returning HTTP 5xx) if that not-null constraint can't be fulfilled. – Marcel Stör Aug 11 '17 at 06:00