javaspringspring-bootenumsjson-deserialization

Make Spring Boot JSON enum deserialization strict, so it does not silently convert invalid values into null


I am using Java Spring Boot @RestController with an object containing enum fields. Spring automagically deserializes the JSON to the MyRequest object.

@RestController
public class MyController {
    @PostMapping(path = "/operation")
    public ResponseEntity<MyResponse> operation(@Valid @RequestBody MyRequest request) {
        ...
    }
}

public class MyRequest {
    private MyEnum1 field1;
    private MyEnum2 field2;
    private MyEnum3 field3;
    private MyEnum4 field4;
    private MyEnum5 field5;
    private MyEnum6 field6;
    ... // really a lot of various enum fields!
}

public enum MyEnum1 {
    VAL1, VAL2, VAL3;
}

The problem is that if the JSON contains completely invalid value of the enum field, the deserializer silently converts them to null, without any exception.

{
    "field1": "BLAHBLAH",
    ...
}

This is user-unfriendly and treacherous.

I know that I may write custom JSON deserializers for each enum, but the solution is cumbersome and non-elegant.

Is there a way to globally set the JSON enum deserializer to a "strict mode", so if the value is invalid it throws an exception? If so, how and where?


EDIT:

As @x4rf41 properly stated in his (accepted) answer, the strict evaluation of enums is indeed on by default. I hadn't realized that somewhere in our code we had it turned off:

featuresToEnable(new Object[]{DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL})

The moral of the story, in hindsight, is to never set JSON deserialization features globally for the whole application when you need some special behaviour, but always configure your own ObjectMapper for your specific need.


Solution

  • That feature should be disabled by default.

    But if you want to set it explicitly you can do it like this:

    in your properties:

    spring.jackson.deserialization.read-unknown-enum-values-as-null=false
    

    or as an alternative in a configuration class (actually any bean would work, just make sure it happens early):

    @Autowired
    public void configureJackson(ObjectMapper objectMapper) {
       objectMapper.disable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL);
    }
    

    Because it should actually be like this by default, I am wondering why it is not for you. Do you enable it somewhere? Which Spring Boot version are you using?