“This is the third day of my participation in the First Challenge 2022, for more details: First Challenge 2022”.

The introduction

Hello, this is Anyin.

Following on from the previous article, we “gracefully” implement the front end dictionary enumeration value echo, when the database query returns a code value, we can serialize in Spring MVC according to the annotation information, Automatically convert the code value into an object containing text and code value and return it to the front end, so that the front end can conveniently get the corresponding text value for page rendering.

This is in the query scenario, but what about in the edit or add scenario?

In edit or add scenarios, the front end will give the back end a code value, and the back end will receive the enumeration value as a String, then convert it into the corresponding enumeration object in the business code, and finally perform the corresponding business operation. The logic of the transformation is as follows:

    public static SexEnum get(String code){
        for(SexEnum item : values()) {
            if(code.equals(item.getCode())){
                returnitem; }}// Return the default or throw an exception
        return SexEnum.MAN;
    }
Copy the code

There are two problems with this:

  1. This transformation method is required for all enumeration objects passed by the front end
  2. Enumeration values passed by the front end could not be verified for correctness

Train of thought

There are different solutions to the above two problems. For example, in question 1, we can abstract the get method by inheriting the parent class and make all the enumerated classes inherit the parent class. Question 2: You can verify that the enumeration values are correct by using annotations +AOP.

Of course, let’s share another solution here. In the previous article we solved this problem by serialization, so we will solve this problem by deserialization. When deserializing the JSON string, we take the Class object of the current enumeration field, match the value to the enumeration object, and return it.

implementation

The overall code is pretty simple. We implement a StringAsDictDeserializer class that inherits JsonDeserializer. Its generic type is BaseEnum, which is the abstract interface through which we define all enumerated objects. Finally, the ContextualDeserializer interface is required to obtain the Class object of the current enumeration field.

The code is as follows:

@Slf4j
@JacksonStdImpl
public class StringAsDictDeserializer extends JsonDeserializer<BaseEnum> implements ContextualDeserializer {

    public StringAsDictDeserializer(a){}

    privateClass<? > clazz;public StringAsDictDeserializer(Class
        clazz){
        this.clazz = clazz;
    }

    @Override
    public BaseEnum deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
        // The value passed by the front end
        String value = p.getValueAsString();
        // Get the corresponding enumeration object through traversal
        BaseEnum type = Arrays.stream(clazz.getEnumConstants()).map(t -> (BaseEnum) t)
                .filter(t -> Objects.equals(t.getCode(), value))
                .findAny().orElse(null);
        if(type == null) {throw new DictSerializerException("value is error, not found enum type");
        }
        return type;
    }

    @Override
    publicJsonDeserializer<? > createContextual(DeserializationContext ctxt, BeanProperty property)throws JsonMappingException {
        // Custom deserializerClass<? > typeClazz = property.getType().getRawClass();return newStringAsDictDeserializer(typeClazz); }}Copy the code

Note @jacksonStdimpl. The createContextual method of ContextualDeserializer interface only applies if you add it, and only then can you get the BeanProperty object. To get the Class object of the target enumeration Class.

test

Next, let’s test our code. In the Controller receiving entity class, we add the corresponding annotation configuration as follows:

    @Data
    public static class TestForm{
        @JsonDeserialize(using = StringAsDictDeserializer.class)
        private SexEnum sex;

        @JsonDeserialize(using = StringAsDictDeserializer.class)
        private StatusEnum status;
    }
Copy the code

Request parameters using Postman:

Console print result:

The last

Above, we implement the backend to receive dictionary enumeration values, have you learned?

Anyin Cloud