thmasker
thmasker

Reputation: 638

Spring parse String to enum before entering the controller

I have the following controller:

public interface SaveController {
  @PostMapping(value = "/save")
  @ResponseStatus(code = HttpStatus.CREATED)
  void save(@RequestBody @Valid SaveRequest saveRequest);
}

SaveRequest corresponds to:

public class SaveRequest {
  @NotNull
  private SaveType type;

  private String name;
}

and SaveType:

public enum SaveType {
  DAILY, WEEKLY, MONTHLY;
}

The controller does not receive the enum itself, but a camelCase String. I need to convert that String into the corresponding enum. For instance:

I've tried using the Spring Converter class, which does not work when the enum is inside an object (at least I don't know how to make it work in such times).

I honestly don't know what else to try

Upvotes: 1

Views: 1736

Answers (2)

Litrico
Litrico

Reputation: 107

https://www.baeldung.com/jackson-serialize-enums This site should probably give you plenty of options.

Best is probably something like this:

public enum SaveType {
    
    DAILY, WEEKLY, MONTHLY;

    @JsonCreator
    public static SaveType saveTypeforValue(String value) {
        return SaveType.valueOf(value.toUpperCase());    
    }
}

Upvotes: 3

Naveen Vignesh
Naveen Vignesh

Reputation: 1359

What you require is to have custom annotation with a custom validation class for Enum.

javax.validation library doesn't have inbuilt support for enums.

Validation class

public class SaveTypeSubSetValidator implements ConstraintValidator<SaveTypeSubset, SaveType> {
    private SaveType[] subset;

    @Override
    public void initialize(SaveTypeSubset constraint) {
        this.subset = constraint.anyOf();
    }

    @Override
    public boolean isValid(SaveType value, ConstraintValidatorContext context) {
        return value == null || Arrays.asList(subset).contains(value);
    }
}

interface for validation annotation with validation message

@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = SaveTypeSubSetValidator.class)
public @interface SaveTypeSubset {
    SaveType[] anyOf();
    String message() default "must be any of {anyOf}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Usage

@SaveTypeSubset(anyOf = {SaveType.NEW, SaveType.OLD})
private SaveType SaveType;

This is one way. More ways are mentioned in this article.

Upvotes: 0

Related Questions