新增:新增修改基础信息 API(优化 Jackson 针对通用枚举接口 IEnum 的序列化和反序列化)

This commit is contained in:
2023-01-09 22:41:09 +08:00
parent 5252c54c48
commit 76fb698a37
21 changed files with 442 additions and 140 deletions

View File

@@ -44,12 +44,12 @@ public class BigNumberSerializer extends NumberSerializer {
}
@Override
public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException {
public void serialize(Number value, JsonGenerator generator, SerializerProvider provider) throws IOException {
// 序列化为字符串
if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) {
super.serialize(value, gen, provider);
super.serialize(value, generator, provider);
} else {
gen.writeString(value.toString());
generator.writeString(value.toString());
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.charles7c.cnadmin.common.config.jackson;
import java.io.IOException;
import java.lang.reflect.Field;
import com.baomidou.mybatisplus.annotation.IEnum;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
/**
* 通用枚举接口 IEnum 反序列化器
*
* @author Charles7c
* @since 2023/1/8 13:56
*/
@JacksonStdImpl
public class IEnumDeserializer extends JsonDeserializer<IEnum> {
/** 静态实例 */
public static final IEnumDeserializer SERIALIZER_INSTANCE = new IEnumDeserializer();
@Override
public IEnum 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}
*/
public IEnum 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(IEnum.class, fieldTypeClass)) {
IEnum iEnum = (IEnum)enumConstant;
if (iEnum.getValue().equals(Integer.valueOf(value))) {
return iEnum;
}
}
}
return null;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.charles7c.cnadmin.common.config.jackson;
import java.io.IOException;
import com.baomidou.mybatisplus.annotation.IEnum;
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;
/**
* 通用枚举接口 IEnum 序列化器
*
* @author Charles7c
* @since 2023/1/8 13:56
*/
@JacksonStdImpl
public class IEnumSerializer extends JsonSerializer<IEnum> {
/** 静态实例 */
public static final IEnumSerializer SERIALIZER_INSTANCE = new IEnumSerializer();
@Override
public void serialize(IEnum value, JsonGenerator generator, SerializerProvider serializers) throws IOException {
generator.writeObject(value.getValue());
}
}

View File

@@ -16,7 +16,6 @@
package top.charles7c.cnadmin.common.config.jackson;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
@@ -30,11 +29,11 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.baomidou.mybatisplus.annotation.IEnum;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
@@ -55,7 +54,7 @@ import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
public class JacksonConfiguration {
/**
* 全局配置序列化返回 JSON 处理
* 针对数值类型Long、BigInteger、BigDecimal时间类型LocalDateTime、LocalDate、LocalTime 的序列化和反序列化
*/
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
@@ -64,23 +63,14 @@ public class JacksonConfiguration {
String timeFormatPattern = "HH:mm:ss";
return builder -> {
// 针对通用枚举 IEnum 的转换
builder.serializerByType(IEnum.class, new JsonSerializer<IEnum<Integer>>() {
@Override
public void serialize(IEnum<Integer> value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
gen.writeNumber(value.getValue());
}
});
// 针对 Long、BigInteger、BigDecimal 的转换
// 针对数值类型Long、BigInteger、BigDecimal 的序列化和反序列化
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);
javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
// 针对 LocalDateTime、LocalDate、LocalTime 的转换
// 针对时间类型:LocalDateTime、LocalDate、LocalTime 的序列化和反序列化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimeFormatPattern);
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
@@ -97,4 +87,21 @@ public class JacksonConfiguration {
log.info(">>>初始化 Jackson 配置<<<");
};
}
/**
* 针对通用枚举接口 IEnum 的序列化和反序列化
*/
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(IEnum.class, IEnumSerializer.SERIALIZER_INSTANCE);
SimpleDeserializersWrapper deserializers = new SimpleDeserializersWrapper();
deserializers.addDeserializer(IEnum.class, IEnumDeserializer.SERIALIZER_INSTANCE);
simpleModule.setDeserializers(deserializers);
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.registerModule(simpleModule);
return objectMapper;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.charles7c.cnadmin.common.config.jackson;
import lombok.extern.slf4j.Slf4j;
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 枚举类型,则是找它的接口 IEnum 的反序列化器);<br>
* 4. 同默认 3。
* </p>
*
* @author Charles7c
* @since 2023/1/8 13:28
*/
@Slf4j
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 (deser != null) {
return deser;
}
// 重写增强开始查找指定枚举类型的接口的反序列化器例如GenderEnum 枚举类型,则是找它的接口 IEnum 的反序列化器)
for (Class<?> typeInterface : type.getInterfaces()) {
deser = this._classMappings.get(new ClassKey(typeInterface));
if (deser != null) {
return deser;
}
}
return null;
}
}