mirror of
				https://github.com/continew-org/continew-starter.git
				synced 2025-11-04 09:01:40 +08:00 
			
		
		
		
	feat(json/jackson): 新增枚举接口序列化及反序列化配置
This commit is contained in:
		@@ -17,6 +17,7 @@
 | 
			
		||||
package top.continew.starter.json.jackson.autoconfigure;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.date.DatePattern;
 | 
			
		||||
import com.fasterxml.jackson.databind.module.SimpleModule;
 | 
			
		||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 | 
			
		||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
 | 
			
		||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
 | 
			
		||||
@@ -30,8 +31,12 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
 | 
			
		||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.PropertySource;
 | 
			
		||||
import top.continew.starter.core.enums.BaseEnum;
 | 
			
		||||
import top.continew.starter.core.util.GeneralPropertySourceFactory;
 | 
			
		||||
import top.continew.starter.json.jackson.serializer.BaseEnumDeserializer;
 | 
			
		||||
import top.continew.starter.json.jackson.serializer.BaseEnumSerializer;
 | 
			
		||||
import top.continew.starter.json.jackson.serializer.BigNumberSerializer;
 | 
			
		||||
import top.continew.starter.json.jackson.serializer.SimpleDeserializersWrapper;
 | 
			
		||||
 | 
			
		||||
import java.math.BigInteger;
 | 
			
		||||
import java.time.LocalDate;
 | 
			
		||||
@@ -54,26 +59,53 @@ public class JacksonAutoConfiguration {
 | 
			
		||||
    @Bean
 | 
			
		||||
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
 | 
			
		||||
        return builder -> {
 | 
			
		||||
            // 针对大数值的序列化处理
 | 
			
		||||
            JavaTimeModule javaTimeModule = new JavaTimeModule();
 | 
			
		||||
            javaTimeModule.addSerializer(Long.class, BigNumberSerializer.SERIALIZER_INSTANCE);
 | 
			
		||||
            javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.SERIALIZER_INSTANCE);
 | 
			
		||||
            javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.SERIALIZER_INSTANCE);
 | 
			
		||||
            // 针对时间类型:LocalDateTime 的序列化和反序列化处理
 | 
			
		||||
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
 | 
			
		||||
            javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
 | 
			
		||||
            javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
 | 
			
		||||
            // 针对时间类型:LocalDate 的序列化和反序列化处理
 | 
			
		||||
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN);
 | 
			
		||||
            javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter));
 | 
			
		||||
            javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter));
 | 
			
		||||
            // 针对时间类型:LocalTime 的序列化和反序列化处理
 | 
			
		||||
            DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN);
 | 
			
		||||
            javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter));
 | 
			
		||||
            javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter));
 | 
			
		||||
            JavaTimeModule javaTimeModule = this.timeModule();
 | 
			
		||||
            SimpleModule simpleModule = this.simpleModule();
 | 
			
		||||
            builder.timeZone(TimeZone.getDefault());
 | 
			
		||||
            builder.modules(javaTimeModule);
 | 
			
		||||
            builder.modules(javaTimeModule, simpleModule);
 | 
			
		||||
            log.debug("[ContiNew Starter] - Auto Configuration 'Jackson' completed initialization.");
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 日期时间序列化及反序列化配置
 | 
			
		||||
     *
 | 
			
		||||
     * @return JavaTimeModule /
 | 
			
		||||
     * @since 1.0.0
 | 
			
		||||
     */
 | 
			
		||||
    private JavaTimeModule timeModule() {
 | 
			
		||||
        // 针对大数值的序列化处理
 | 
			
		||||
        JavaTimeModule javaTimeModule = new JavaTimeModule();
 | 
			
		||||
        javaTimeModule.addSerializer(Long.class, BigNumberSerializer.SERIALIZER_INSTANCE);
 | 
			
		||||
        javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.SERIALIZER_INSTANCE);
 | 
			
		||||
        javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.SERIALIZER_INSTANCE);
 | 
			
		||||
        // 针对时间类型:LocalDateTime 的序列化和反序列化处理
 | 
			
		||||
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
 | 
			
		||||
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
 | 
			
		||||
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
 | 
			
		||||
        // 针对时间类型:LocalDate 的序列化和反序列化处理
 | 
			
		||||
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN);
 | 
			
		||||
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter));
 | 
			
		||||
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter));
 | 
			
		||||
        // 针对时间类型:LocalTime 的序列化和反序列化处理
 | 
			
		||||
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN);
 | 
			
		||||
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(timeFormatter));
 | 
			
		||||
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(timeFormatter));
 | 
			
		||||
        return javaTimeModule;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 枚举序列化及反序列化配置
 | 
			
		||||
     *
 | 
			
		||||
     * @return SimpleModule /
 | 
			
		||||
     * @since 2.4.0
 | 
			
		||||
     */
 | 
			
		||||
    private SimpleModule simpleModule() {
 | 
			
		||||
        SimpleModule simpleModule = new SimpleModule();
 | 
			
		||||
        simpleModule.addSerializer(BaseEnum.class, BaseEnumSerializer.SERIALIZER_INSTANCE);
 | 
			
		||||
        SimpleDeserializersWrapper deserializers = new SimpleDeserializersWrapper();
 | 
			
		||||
        deserializers.addDeserializer(BaseEnum.class, BaseEnumDeserializer.SERIALIZER_INSTANCE);
 | 
			
		||||
        simpleModule.setDeserializers(deserializers);
 | 
			
		||||
        return simpleModule;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,76 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * <p>
 | 
			
		||||
 * http://www.gnu.org/licenses/lgpl.html
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package top.continew.starter.json.jackson.serializer;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.ClassUtil;
 | 
			
		||||
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.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 | 
			
		||||
import top.continew.starter.core.enums.BaseEnum;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 枚举接口 BaseEnum 反序列化器
 | 
			
		||||
 *
 | 
			
		||||
 * @author Charles7c
 | 
			
		||||
 * @see BaseEnum
 | 
			
		||||
 * @since 2.4.0
 | 
			
		||||
 */
 | 
			
		||||
@JacksonStdImpl
 | 
			
		||||
public class BaseEnumDeserializer extends JsonDeserializer<BaseEnum> {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 静态实例
 | 
			
		||||
     */
 | 
			
		||||
    public static final BaseEnumDeserializer SERIALIZER_INSTANCE = new BaseEnumDeserializer();
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public BaseEnum deserialize(JsonParser jsonParser,
 | 
			
		||||
                                DeserializationContext deserializationContext) throws IOException {
 | 
			
		||||
        Class<?> targetClass = jsonParser.getCurrentValue().getClass();
 | 
			
		||||
        String fieldName = jsonParser.getCurrentName();
 | 
			
		||||
        String value = jsonParser.getText();
 | 
			
		||||
        return this.getEnum(targetClass, value, fieldName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通过某字段对应值获取枚举实例,获取不到时为 {@code null}
 | 
			
		||||
     *
 | 
			
		||||
     * @param targetClass 目标类型
 | 
			
		||||
     * @param value       字段值
 | 
			
		||||
     * @param fieldName   字段名
 | 
			
		||||
     * @return 对应枚举实例 ,获取不到时为 {@code null}
 | 
			
		||||
     */
 | 
			
		||||
    private BaseEnum getEnum(Class<?> targetClass, String value, String fieldName) {
 | 
			
		||||
        Field field = ReflectUtil.getField(targetClass, fieldName);
 | 
			
		||||
        Class<?> fieldTypeClass = field.getType();
 | 
			
		||||
        Object[] enumConstants = fieldTypeClass.getEnumConstants();
 | 
			
		||||
        for (Object enumConstant : enumConstants) {
 | 
			
		||||
            if (ClassUtil.isAssignable(BaseEnum.class, fieldTypeClass)) {
 | 
			
		||||
                BaseEnum baseEnum = (BaseEnum)enumConstant;
 | 
			
		||||
                if (baseEnum.getValue().equals(Integer.valueOf(value))) {
 | 
			
		||||
                    return baseEnum;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * <p>
 | 
			
		||||
 * http://www.gnu.org/licenses/lgpl.html
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package top.continew.starter.json.jackson.serializer;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.core.JsonGenerator;
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonSerializer;
 | 
			
		||||
import com.fasterxml.jackson.databind.SerializerProvider;
 | 
			
		||||
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 | 
			
		||||
import top.continew.starter.core.enums.BaseEnum;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 枚举接口 BaseEnum 序列化器
 | 
			
		||||
 *
 | 
			
		||||
 * @author Charles7c
 | 
			
		||||
 * @see BaseEnum
 | 
			
		||||
 * @since 2.4.0
 | 
			
		||||
 */
 | 
			
		||||
@JacksonStdImpl
 | 
			
		||||
public class BaseEnumSerializer extends JsonSerializer<BaseEnum> {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 静态实例
 | 
			
		||||
     */
 | 
			
		||||
    public static final BaseEnumSerializer SERIALIZER_INSTANCE = new BaseEnumSerializer();
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void serialize(BaseEnum value, JsonGenerator generator, SerializerProvider serializers) throws IOException {
 | 
			
		||||
        generator.writeObject(value.getValue());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,65 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * <p>
 | 
			
		||||
 * http://www.gnu.org/licenses/lgpl.html
 | 
			
		||||
 * <p>
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package top.continew.starter.json.jackson.serializer;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.BeanDescription;
 | 
			
		||||
import com.fasterxml.jackson.databind.DeserializationConfig;
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonDeserializer;
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonMappingException;
 | 
			
		||||
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
 | 
			
		||||
import com.fasterxml.jackson.databind.type.ClassKey;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 反序列化器包装类(重写 Jackson 反序列化枚举方法,参阅:FasterXML/jackson-databind#2842)
 | 
			
		||||
 *
 | 
			
		||||
 * <p>
 | 
			
		||||
 * 默认处理:<br>
 | 
			
		||||
 * 1. Jackson 会先查找指定枚举类型对应的反序列化器(例如:GenderEnum 枚举类型,则是找 GenderEnum 枚举类型的对应反序列化器);<br>
 | 
			
		||||
 * 2. 如果找不到则开始查找 Enum 类型(所有枚举父类)的反序列化器;<br>
 | 
			
		||||
 * 3. 如果都找不到则会采用默认的枚举反序列化器(它仅能根据枚举类型的 name、ordinal 来进行反序列化)。
 | 
			
		||||
 * </p>
 | 
			
		||||
 * <p>
 | 
			
		||||
 * 重写增强后:<br>
 | 
			
		||||
 * 1. 同默认 1;<br>
 | 
			
		||||
 * 2. 同默认 2;<br>
 | 
			
		||||
 * 3. 如果也找不到 Enum 类型(所有枚举父类)的反序列化器,开始查找指定枚举类型的接口的反序列化器(例如:GenderEnum 枚举类型,则是找它的接口 BaseEnum 的反序列化器);<br>
 | 
			
		||||
 * 4. 同默认 3。
 | 
			
		||||
 * </p>
 | 
			
		||||
 *
 | 
			
		||||
 * @author Charles7c
 | 
			
		||||
 * @since 2.4.0
 | 
			
		||||
 */
 | 
			
		||||
public class SimpleDeserializersWrapper extends SimpleDeserializers {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public JsonDeserializer<?> findEnumDeserializer(Class<?> type,
 | 
			
		||||
                                                    DeserializationConfig config,
 | 
			
		||||
                                                    BeanDescription beanDesc) throws JsonMappingException {
 | 
			
		||||
        JsonDeserializer<?> deser = super.findEnumDeserializer(type, config, beanDesc);
 | 
			
		||||
        if (null != deser) {
 | 
			
		||||
            return deser;
 | 
			
		||||
        }
 | 
			
		||||
        // 重写增强:开始查找指定枚举类型的接口的反序列化器(例如:GenderEnum 枚举类型,则是找它的接口 BaseEnum 的反序列化器)
 | 
			
		||||
        for (Class<?> typeInterface : type.getInterfaces()) {
 | 
			
		||||
            deser = this._classMappings.get(new ClassKey(typeInterface));
 | 
			
		||||
            if (null != deser) {
 | 
			
		||||
                return deser;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user