SpringMVC 之 自定义系列化(Get请求无效)
此方式仅仅对 @RequestBody 方式的请求生效,对 parame 方式传参并不生效(?key=value&key=value),比如 Get 请求
GET 请求参数配置请参考: https://www.cnblogs.com/chxlay/p/16028839.html
>>>>>>>>>>>>> 码云中有封装号的:https://gitee.com/chxlay/iserver-common.git <<<<<<<<<<<<<<<<<<<<<
Java8 时间自定义系列化 与 反系列化:
public class Java8TimeModule extends SimpleModule { public Java8TimeModule() { super(PackageVersion.VERSION); // ======================= 时间序列化规则 =============================== // yyyy-MM-dd HH:mm:ss this.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // yyyy-MM-dd this.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); // HH:mm:ss this.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); // ======================= 时间反序列化规则 ============================== // yyyy-MM-dd HH:mm:ss this.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // yyyy-MM-dd this.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); // HH:mm:ss this.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss"))); } }
将自定义的系列化规则配置到服务中:(本文页底和自定义枚举系列化一起)
自定义枚举系列化:
1、抽象约束枚举接口:
@JsonDeserialize(using = IServerEnumDeserializer.class) public interface IServerEnum extends Serializable { /** * 获取枚举编码 * * @return */ int getCode(); /** * 获取枚举名称 * * @return */ default String getName() { return this.name(); } /** * 获取枚举名称 * * @return */ String name(); /** * 根据枚举名称获取枚举对象 * * @param clazz * @param name * @param <E> * @return */ @SneakyThrows static <E extends Enum<E> & IServerEnum> E sourceOf(Class<E> clazz, String name) { Method valuesMethod = clazz.getMethod("values"); E[] enumInstanceArr = (E[]) valuesMethod.invoke(null); for (E enumInstance : enumInstanceArr) { if (Objects.equals(enumInstance.name(), name)) { return enumInstance; } } throw ExceptionUtil.create(IRuntimeException.class, ErrorResult.PARAMETER_ERROR); } /** * 根据编码获取枚举对象 * * @param clazz * @param code * @param <E> * @return */ @SneakyThrows static <E extends Enum<E> & IServerEnum> E codeOf(Class<E> clazz, int code) { Method valuesMethod = clazz.getMethod("values"); E[] enumInstanceArr = (E[]) valuesMethod.invoke(null); for (E enumInstance : enumInstanceArr) { if (code == enumInstance.getCode()) { return enumInstance; } } throw ExceptionUtil.create(IRuntimeException.class, ErrorResult.PARAMETER_ERROR); } }
具体枚举类:
public enum SexEnum implements IServerEnum<String> { /** * 男性 */ MALE(1, "男"), /** * 女性 */ FEMALE(2, "女"), /** * 未知 */ UNKNOWN(3, "未知"); /** * 枚举编码 */ @EnumValue private int code; /** * 枚举值 */ private String value; }
手动编写反系列化器(根据自己的业务需求自行编写逻辑)
public class IServerEnumDeserializer extends JsonDeserializer<IServerEnum> { @Override public IServerEnum deserialize(JsonParser jp, DeserializationContext deserializationContext) throws IOException { JsonNode node = jp.getCodec().readTree(jp); String currentName = jp.currentName(); Object currentValue = jp.getCurrentValue(); @SuppressWarnings("rawtypes") Class enumClazz = BeanUtils.findPropertyType(currentName, currentValue.getClass()); IServerEnum iEnum; if (node instanceof IntNode) { // 当客户端传值为枚举的 code 的值得时候 iEnum = (IServerEnum) IServerEnum.codeOf(enumClazz, node.asInt()); } else if (node instanceof TextNode) { // 当客户端传值为 枚举的 name 时候 iEnum = (IServerEnum) IServerEnum.sourceOf(enumClazz, node.asText()); } else { // 若传参的是枚举对象时, JsonNode 为 ObjectNode 类,枚举对象的数据放在一个 LinkedHashMap 中,只需要从 Map 中读取出 name 即可 iEnum = (IServerEnum) IServerEnum.sourceOf(enumClazz, node.get("name").asText()); } return iEnum; } }
public class IServerEnumSerializer extends JsonSerializer<IServerEnum> { @Override public void serialize(IServerEnum iServerEnum, JsonGenerator generator, SerializerProvider provider) throws IOException { // 枚举的code 作为系列化 int code = iServerEnum.getCode(); generator.writeNumber(code); } }
将反系列化器注册:
public class IEnumModule extends SimpleModule { public IEnumModule() { super(PackageVersion.VERSION); super // 自定义凡系列化 .addSerializer(IServerEnum.class, new IServerEnumSerializer()) // 自定义通用枚举类反系列化处理 .addDeserializer(IServerEnum.class, new IServerEnumDeserializer()); } }
转换器配置注册(注册方式二选一即可)
1、简单配置使用
@Configuration @ConditionalOnClass(ObjectMapper.class) @AutoConfigureBefore(JacksonAutoConfiguration.class) public class JacksonConfig { private static final String ASIA_SHANGHAI = "Asia/Shanghai"; /** * 处理 @RequestBody 方式传参的自定义转换 * java8 时间系列化/反系列化 */ @Bean @ConditionalOnMissingBean public Jackson2ObjectMapperBuilderCustomizer java8Customizer() { return (Jackson2ObjectMapperBuilder builder) -> { builder.locale(Locale.CHINA); builder.timeZone(TimeZone.getTimeZone(ASIA_SHANGHAI)); builder.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN); builder.modules(new Java8TimeModule(), new IEnumModule()); }; } }
全配置:(有些类这里没有公示)
@Configuration @RequiredArgsConstructor @ConditionalOnClass(ObjectMapper.class) @AutoConfigureBefore(JacksonAutoConfiguration.class) public class JacksonConfig { private static final String ASIA_SHANGHAI = "Asia/Shanghai"; private final HttpServletRequest request; @Bean @Primary @ConditionalOnMissingBean public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder // 地区时区配置 .locale(Locale.CHINA).timeZone(TimeZone.getTimeZone(ASIA_SHANGHAI)) // 时间格式 .simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN) .createXmlMapper(false).build(); objectMapper // Java8 时间系列化 .registerModule(new Java8TimeModule()) // 自定义枚举系列化 .registerModule(new IEnumModule()) // 人民币金额系列化、反系列化规则(元 <====> 分) .registerModule(new MoneyPennyModule(request)) // 空的 Bean 不报错 .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) // 如果 json 中字段是 实体类中不存在的,不报错 .configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false) // 如果存在位置属性,则忽略 .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) // 允许 Json 中的 key 没有双引号 .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) // 允许 Json 中的 key 是 单引号的 .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) // 允许 整数 以 0 开头 .configure(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS.mappedFeature(), true) // 允许存在 回车 换行符号 .configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), true) // 忽略 NULL 值 // .setSerializationInclusion(JsonInclude.Include.NON_NULL) ; return objectMapper; } }
本文来自博客园,作者:Vermeer,转载请注明原文链接:https://www.cnblogs.com/chxlay/p/16028823.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步