Jackson自定义JsonSerializer多字段拼接及反序列化问题
解决方案:Jackson自定义DatePair序列化/反序列化
针对遇到的四个问题,逐一解决如下:
1. 解决序列化Model1的异常 & 实现日期不带引号的格式
异常原因:使用writeRaw直接输出非JSON标准值的内容,破坏了对象内部的JSON结构(对象字段值必须是合法JSON类型:字符串、数字、对象等)。
解决方法:将DatePair序列化为单个字符串值,用gen.writeString()替代writeRaw,同时手动格式化日期为无引号的字符串后拼接。
2. 让@JsonFormat作用于DatePair的日期字段
问题原因:全局序列化器默认无法读取父对象字段上的@JsonFormat注解。
解决方法:通过SerializerProvider获取当前字段的注解配置,动态选择日期格式化规则(优先使用注解配置,无注解时用全局默认)。
修改后的序列化器
public static class DatePairJsonSerializer extends JsonSerializer<DatePair> { @Override public void serialize(DatePair value, JsonGenerator gen, SerializerProvider serializers) throws IOException { // 获取当前字段的@JsonFormat注解 JsonFormat format = serializers.getAnnotationIntrospector().findFormat(serializers.getContextualType()); // 初始化日期格式化器 SimpleDateFormat dateFormat; if (format != null) { dateFormat = new SimpleDateFormat(format.pattern()); dateFormat.setTimeZone(TimeZone.getTimeZone(format.timezone())); } else { dateFormat = (SimpleDateFormat) serializers.getDateFormat(); } // 格式化日期并拼接目标字符串 String date1Str = dateFormat.format(value.getDate1()); String date2Str = dateFormat.format(value.getDate2()); String serializedStr = String.format("(%s, %s)", date1Str, date2Str); // 写入合法的JSON字符串值 gen.writeString(serializedStr); } }
3. 匹配的反序列化器实现
将形如"(2025/06/22 10:02:48.000, 2025/06/22 10:02:48.000)"的字符串解析为DatePair:
public static class DatePairJsonDeserializer extends JsonDeserializer<DatePair> { @Override public DatePair deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String rawValue = p.getText(); // 清理字符串:去除首尾括号和多余空格 String cleaned = rawValue.replaceAll("^\\(|\\)$", "").trim(); String[] dateSegments = cleaned.split(",\\s*"); // 获取字段上的@JsonFormat注解配置 JsonFormat format = ctxt.getAnnotationIntrospector().findFormat(ctxt.getContextualType()); SimpleDateFormat dateFormat; if (format != null) { dateFormat = new SimpleDateFormat(format.pattern()); dateFormat.setTimeZone(TimeZone.getTimeZone(format.timezone())); } else { dateFormat = (SimpleDateFormat) ctxt.getDateFormat(); } DatePair datePair = new DatePair(); try { datePair.setDate1(dateFormat.parse(dateSegments[0])); datePair.setDate2(dateFormat.parse(dateSegments[1])); } catch (ParseException e) { throw new IOException("Failed to parse DatePair string: " + rawValue, e); } return datePair; } }
注册反序列化器
在main方法中添加反序列化器到Module:
// 原有的序列化器注册后,添加反序列化器 simpleModule.addDeserializer(DatePair.class, new DatePairJsonDeserializer());
测试结果
- 单独序列化DatePair:输出
"(2025-06-22 10:02:48, 2025-06-22 10:02:48)"(合法JSON字符串,日期无引号) - 序列化Model1:输出
{"datePair":"(2025/06/22 10:02:48.000, 2025/06/22 10:02:48.000)"}(@JsonFormat的格式和时区生效) - 反序列化:可将上述JSON字符串正确解析为DatePair对象
关键注意事项
- 必须保证生成的JSON结构合法:
DatePair必须作为字符串值存在,不能输出裸的括号内容 - 通过注解 introspector 获取字段级的格式配置,实现灵活的格式化规则切换
- 反序列化时要处理字符串解析异常,提升代码鲁棒性
内容的提问来源于stack exchange,提问作者Guo
相关产品推荐
相关产品推荐

