Reputation: 23
I have some simple enums like below.
public enum Status {
ACTIVE,
PASSIVE;
private Status() {
}
}
I have a String status field in my REST service input object.
It converts it to PASSIVE when the service receives both requests.
CASE 1 status = 1
{
"name": "Walter",
"surname": "White"
"status": "1"
}
CASE 2 status = "PASSIVE"
{
"name": "Walter",
"surname": "White"
"status": "PASSIVE"
}
I do not want the default convertor accepts the numeric inputs (CASE 1). I mean I do not want it to convert 1 to PASSIVE by using the index of the enum.
I want it only accepts Non numeric values as it is in CASE 2.
Also consider that I have many enums like this and I want to apply the restriction to all my enums.
How can I make it works as I explained above ?
Upvotes: 2
Views: 2033
Reputation: 18480
Update:
By default, Number for Enum deserialize by mapping enum ordinal. Add configuration DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS as true in ObjectMapper which is by default false.
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper configureObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
return objectMapper;
}
}
Another way is to write a custom annotation for enum validation. And use it on the field with possible values
@EnumNamePattern
private Status status;
Custom Annotation for enum validation
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = EnumNamePatternValidator.class)
public @interface EnumNamePattern {
String message() default "invalid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
And write validator for the annotation
public class EnumNamePatternValidator implements ConstraintValidator<EnumNamePattern, Enum<?>> {
@Override
public boolean isValid(Enum<?> value, ConstraintValidatorContext context) {
if (value == null) return true;
return Arrays.stream(Status.values()).anyMatch(e -> e.name().equals(value.name()));
}
}
Upvotes: 2