mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-13 00:57:09 +08:00
feat(json/jackson): 新增枚举接口序列化及反序列化配置
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
package top.continew.starter.json.jackson.autoconfigure;
|
package top.continew.starter.json.jackson.autoconfigure;
|
||||||
|
|
||||||
import cn.hutool.core.date.DatePattern;
|
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.JavaTimeModule;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
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.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
import top.continew.starter.core.enums.BaseEnum;
|
||||||
import top.continew.starter.core.util.GeneralPropertySourceFactory;
|
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.BigNumberSerializer;
|
||||||
|
import top.continew.starter.json.jackson.serializer.SimpleDeserializersWrapper;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
@@ -54,26 +59,53 @@ public class JacksonAutoConfiguration {
|
|||||||
@Bean
|
@Bean
|
||||||
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
|
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
|
||||||
return builder -> {
|
return builder -> {
|
||||||
// 针对大数值的序列化处理
|
JavaTimeModule javaTimeModule = this.timeModule();
|
||||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
SimpleModule simpleModule = this.simpleModule();
|
||||||
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));
|
|
||||||
builder.timeZone(TimeZone.getDefault());
|
builder.timeZone(TimeZone.getDefault());
|
||||||
builder.modules(javaTimeModule);
|
builder.modules(javaTimeModule, simpleModule);
|
||||||
log.debug("[ContiNew Starter] - Auto Configuration 'Jackson' completed initialization.");
|
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