如何使用Jackson将ZoneId/ZoneOffset从+03:00序列化为+03.00格式?
Jackson序列化ZoneId/ZoneOffset:将冒号替换为点号的实现方式
一、自定义序列化器(推荐方案)
通过实现Jackson的JsonSerializer接口,精准控制ZoneOffset/ZoneId的序列化输出,将格式中的冒号替换为点号。
1. 针对ZoneOffset的序列化器
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; import java.time.ZoneOffset; public class ZoneOffsetDotSerializer extends JsonSerializer<ZoneOffset> { @Override public void serialize(ZoneOffset value, JsonGenerator gen, SerializerProvider serializers) throws IOException { String formattedOffset = value.toString().replace(':', '.'); gen.writeString(formattedOffset); } }
2. 针对ZoneId的序列化器
ZoneId可能包含普通时区ID(如Europe/Paris)或偏移量(本质是ZoneOffset实例),因此序列化器需要区分处理:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; import java.time.ZoneId; import java.time.ZoneOffset; public class ZoneIdDotSerializer extends JsonSerializer<ZoneId> { @Override public void serialize(ZoneId value, JsonGenerator gen, SerializerProvider serializers) throws IOException { if (value instanceof ZoneOffset) { String formattedOffset = value.toString().replace(':', '.'); gen.writeString(formattedOffset); } else { gen.writeString(value.toString()); } } }
3. 注册序列化器到ObjectMapper
将自定义序列化器注册到Jackson的ObjectMapper中使其生效:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import java.time.ZoneId; import java.time.ZoneOffset; public class SerializationDemo { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule customModule = new SimpleModule(); customModule.addSerializer(ZoneOffset.class, new ZoneOffsetDotSerializer()); customModule.addSerializer(ZoneId.class, new ZoneIdDotSerializer()); mapper.registerModule(customModule); ZoneOffset offset = ZoneOffset.of("+03:00"); System.out.println(mapper.writeValueAsString(offset)); // 输出 "+03.00" ZoneId zoneIdOffset = ZoneId.of("+05:30"); System.out.println(mapper.writeValueAsString(zoneIdOffset)); // 输出 "+05.30" ZoneId zoneId = ZoneId.of("Europe/Paris"); System.out.println(mapper.writeValueAsString(zoneId)); // 输出 "Europe/Paris" } }
二、其他实现方式
1. 序列化后字符串替换(简单场景适用)
如果仅单独序列化ZoneOffset/ZoneId,或能确保JSON中其他内容无需要保留的冒号,可在序列化完成后直接替换字符串:
import com.fasterxml.jackson.databind.ObjectMapper; import java.time.ZoneOffset; public class StringReplaceDemo { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); ZoneOffset offset = ZoneOffset.of("+03:00"); String originalJson = mapper.writeValueAsString(offset); String modifiedJson = originalJson.replace(':', '.'); System.out.println(modifiedJson); // 输出 "+03.00" } }
注意:该方式存在误替换风险,若JSON中其他字段(如日期字符串)包含冒号会被一并修改,仅适合简单场景。
2. 自定义格式化器配合JavaTimeModule
基于Jackson的JavaTimeModule扩展默认序列化逻辑,结合字符串替换实现需求:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.ser.ZoneOffsetSerializer; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; public class FormatterDemo { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); JavaTimeModule module = new JavaTimeModule(); ZoneOffsetSerializer customSerializer = new ZoneOffsetSerializer(DateTimeFormatter.ISO_OFFSET_DATE_TIME) { @Override public void serialize(ZoneOffset value, com.fasterxml.jackson.core.JsonGenerator gen, com.fasterxml.jackson.databind.SerializerProvider serializers) throws IOException { String offsetStr = value.toString().replace(':', '.'); gen.writeString(offsetStr); } }; module.addSerializer(ZoneOffset.class, customSerializer); mapper.registerModule(module); ZoneOffset offset = ZoneOffset.of("+03:00"); System.out.println(mapper.writeValueAsString(offset)); // 输出 "+03.00" } }
内容的提问来源于stack exchange,提问作者trom
相关产品推荐
相关产品推荐

