diff --git a/continew-starter-json/continew-starter-json-jackson/src/main/java/top/continew/starter/json/jackson/autoconfigure/JacksonAutoConfiguration.java b/continew-starter-json/continew-starter-json-jackson/src/main/java/top/continew/starter/json/jackson/autoconfigure/JacksonAutoConfiguration.java index 0a2f6198..a40caf62 100644 --- a/continew-starter-json/continew-starter-json-jackson/src/main/java/top/continew/starter/json/jackson/autoconfigure/JacksonAutoConfiguration.java +++ b/continew-starter-json/continew-starter-json-jackson/src/main/java/top/continew/starter/json/jackson/autoconfigure/JacksonAutoConfiguration.java @@ -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; + } } diff --git a/continew-starter-json/continew-starter-json-jackson/src/main/java/top/continew/starter/json/jackson/serializer/BaseEnumDeserializer.java b/continew-starter-json/continew-starter-json-jackson/src/main/java/top/continew/starter/json/jackson/serializer/BaseEnumDeserializer.java new file mode 100644 index 00000000..cb05eead --- /dev/null +++ b/continew-starter-json/continew-starter-json-jackson/src/main/java/top/continew/starter/json/jackson/serializer/BaseEnumDeserializer.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + *
+ * 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 + *
+ * http://www.gnu.org/licenses/lgpl.html + *
+ * 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
+ * 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
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * 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
+ * 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
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * 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)
+ *
+ *
+ * 默认处理:
+ * 重写增强后:
+ * 1. Jackson 会先查找指定枚举类型对应的反序列化器(例如:GenderEnum 枚举类型,则是找 GenderEnum 枚举类型的对应反序列化器);
+ * 2. 如果找不到则开始查找 Enum 类型(所有枚举父类)的反序列化器;
+ * 3. 如果都找不到则会采用默认的枚举反序列化器(它仅能根据枚举类型的 name、ordinal 来进行反序列化)。
+ *
+ * 1. 同默认 1;
+ * 2. 同默认 2;
+ * 3. 如果也找不到 Enum 类型(所有枚举父类)的反序列化器,开始查找指定枚举类型的接口的反序列化器(例如:GenderEnum 枚举类型,则是找它的接口 BaseEnum 的反序列化器);
+ * 4. 同默认 3。
+ *