自定义枚举序列化与反序列化

抽象枚举接口
package com.example.common.properties.enums;

import cn.hutool.core.util.ObjectUtil;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public interface IEnum {

    Map<Class<?>, Map<String, Enum<?>>> cache = new ConcurrentHashMap<>();

    static <T> T codeOf(Class<T> clazz, String code){
        Map<String, Enum<?>> map = cache.get(clazz);
        if (ObjectUtil.isEmpty(map)){
            map = new ConcurrentHashMap<>();
            Object[] items = clazz.getEnumConstants();
            if (items == null) return null;
            for (Object item : items) {
                if (item instanceof IEnum){
                    IEnum iEnum = (IEnum) item;
                    map.put(iEnum.value(), (Enum<?>) item);
                }
            }
            cache.put(clazz, map);
        }
        return (T) map.get(code);
    }
    
    String value();
    String desc();
}

定义枚举
package com.example.common.properties.enums;

public enum Status implements IEnum {
        ACTION("1"), INACTION("0");
        private String value;
        Status(String value){this.value = value;}

        @Override
        public String value() {
            return value;
        }

        @Override
        public String desc() {
            return null;
        }
    }
定义序列化器
package com.example.common.jackson;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.example.common.properties.enums.IEnum;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class EnumsJacksonSerializer extends JsonSerializer<IEnum> {
    @Override
    public void serialize(IEnum iEnum, JsonGenerator generator, SerializerProvider provider) throws IOException {
        Map<Object, Object> map = new HashMap<>();
        map.put("code", iEnum.value());
        map.put("desc", iEnum.desc());
        generator.writeObject(map);
    }

    public static EnumsJacksonSerializer instance(){
        return new EnumsJacksonSerializer();
    }
}
定义反序列化器
package com.example.common.jackson;

import cn.hutool.core.util.ReflectUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.example.common.properties.enums.IEnum;
import java.io.IOException;
import java.lang.reflect.Field;

public class EnumsJacksonDeserializer extends JsonDeserializer<IEnum> {
    @Override
    public IEnum deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        Field field = ReflectUtil.getField(parser.getCurrentValue().getClass(), parser.getCurrentName());
        return (IEnum) IEnum.codeOf(field.getType(), parser.getText());
    }

    public static EnumsJacksonDeserializer instance(){
        return new EnumsJacksonDeserializer();
    }
}
配置
package com.example.config;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.ClassKey;
import com.example.common.jackson.EnumsJacksonDeserializer;
import com.example.common.jackson.EnumsJacksonSerializer;
import com.example.common.properties.enums.IEnum;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonConfig {

    @Bean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
        SimpleDeserializersWrapper deserializers = new SimpleDeserializersWrapper();
        deserializers.addDeserializer(IEnum.class, new EnumsJacksonDeserializer());
        
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.setDeserializers(deserializers);
        simpleModule.addSerializer(IEnum.class, new EnumsJacksonSerializer());
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }


	/**
     * 根据配置
     * _classMappings映射关系为 com.example.common.properties.enums.IEnum -> com.example.common.jackson.EnumsJacksonDeserializer
     * 传入类型type为 com.example.common.properties.enums.Status
     * 重写遍历传入类型接口列表, 取出接口对应的反序列化器,实现面向接口的枚举反序列化
     */
    public static class SimpleDeserializersWrapper extends SimpleDeserializers{
        @Override
        public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException {
            JsonDeserializer<?> deserializer = super.findEnumDeserializer(type, config, beanDesc);
            if (deserializer != null) {
                return deserializer;
            }
            //找出接口对应的反序列化器
            for (Class<?> typeInterface : type.getInterfaces()) {
                deserializer = this._classMappings.get(new ClassKey(typeInterface));
                if (deserializer != null) {
                    return deserializer;
                }
            }
            return null;
        }
    }
}

序列化时 SimpleSerializers$_findInterfaceMapping(Class<?> cls, ClassKey key) 方法会在 直接映射的序列化器没有的情况下,查询接口对应的序列化器

定义mybatis类型处理器
package com.example.common.properties.enums;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


@MappedTypes({IEnum.class})
public class EnumsTypeHandler<T extends IEnum> implements TypeHandler<T> {

    private T t;

    @Override
    public void setParameter(PreparedStatement statement, int i, T t, JdbcType jdbcType) throws SQLException {
        this.t = t;
        statement.setString(i, t.value());
    }

    @Override
    public T getResult(ResultSet resultSet, String s) throws SQLException {
        return (T) IEnum.codeOf(t.getClass(), resultSet.getString(s));
    }

    @Override
    public T getResult(ResultSet resultSet, int i) throws SQLException {
        return (T) IEnum.codeOf(t.getClass(), resultSet.getString(i));
    }

    @Override
    public T getResult(CallableStatement statement, int i) throws SQLException {
        return (T) IEnum.codeOf(t.getClass(), statement.getString(i));
    }
}
配置mybatis类型处理器
mybatis:
	type-handlers-package: com.example.common.properties.enums
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐