在我使用Spring Boot 2.0.0.M6
,Spring Framework 5.0.1.RELEASE
和Jackson 2.9.2
的项目中,我有一些与使用杰克逊的 JSON序列化相关的问题。
我在application.properties
中配置了以下与杰克逊相关的设置:
spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false
序列化主要按照我的需要工作。尽管如此,我注意到杰克逊似乎截止了毫秒,如果它们是000
。
测试1:序列化Instant,毫秒设置为000
:
Instant.parse("2017-09-14T04:28:48.000Z")
"2017-09-14T04:28:48Z"
测试2:序列化Instant,毫秒设置为某个非000
值:
Instant.parse("2017-09-14T04:28:48.100Z")
"2017-09-14T04:28:48.100Z"
问题:
000
?答案 0 :(得分:3)
似乎有一个杰克逊问题对此here *开放。该链接包含两个解决方法
解决方法1
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
SimpleModule module = new SimpleModule();
module.addSerializer(ZonedDateTime.class, new JsonSerializer<ZonedDateTime>() {
@Override
public void serialize(ZonedDateTime zonedDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeString(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZ").format(zonedDateTime));
}
});
objectMapper.registerModule(module);
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
解决方法2
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(ZonedDateTime.class,
new ZonedDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")));
ObjectMapper mapper = new ObjectMapper().registerModule(javaTimeModule);
*链接已死,因为他们弃用了FasterXML / jackson-datatype-jsr310并将其移至jackson-modules-java8。见https://github.com/FasterXML/jackson-modules-java8/issues/76
答案 1 :(得分:2)
我用这个方法解决:
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(Instant.class, new InstantSerializerWithMilliSecondPrecision());
objectMapper.registerModule(module);
对于InstantSerializerWithMilliSecondPrecision,我使用了以下方法:
public class InstantSerializerWithMilliSecondPrecision extends InstantSerializer {
public InstantSerializerWithMilliSecondPrecision() {
super(InstantSerializer.INSTANCE, false, new DateTimeFormatterBuilder().appendInstant(3).toFormatter());
}
}
现在,即时序列化始终包含毫秒。示例: 2019-09-27T02:59:59.000Z
答案 2 :(得分:1)
Sean Carroll提到的两个变通办法中没有一个有效。最后,我为Instant编写了自己的序列化器。
final ObjectMapper mapper = new ObjectMapper();
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(Instant.class, new KeepMillisecondInstantSerializer());
mapper.registerModule(javaTimeModule);
public class KeepMillisecondInstantSerializer extends JsonSerializer<Instant> {
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
.withZone(ZoneId.of("UTC"));
@Override
public void serialize(final Instant instant, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException {
final String serializedInstant = dateTimeFormatter.format(instant);
jsonGenerator.writeString(serializedInstant);
}
}
我猜杰克逊use Instant.toString()
method to serialize Instant objects默认是。我还找到了some discussions about Instant.toString()
method on StackOverflow。
答案 3 :(得分:0)
除了可以解决Jackson库的错误外,还可以快速解决以下问题: 在您拥有Timestamp变量的POJO类中创建一个字符串变量:
private Timestamp createTimeStamp;
private String stringCreateTimeStamp;
将时间戳值捕获为字符串:
listOfPojo.forEach(pojo-> {
pojo.setStringCreateTimeStamp(request.getcreateTimeStamp().toString());
});
答案 4 :(得分:0)
使用针对 LocalDateTime 和 ZonedDateTime 类的自定义序列化程序来解决。
我的解决方案对我有用,因为我在API响应中仅使用了这两个类来表示日期和时间!我不使用“即时”或“日期”,因此请注意。
@Configuration
class JacksonConfig {
@Bean
fun objectMapper(): ObjectMapper {
val mapper = ObjectMapper()
val javaTimeModule = JavaTimeModule().apply {
addSerializer(LocalDateTime::class.java, KeepMillisecondLocalDateTimeSerializer())
addSerializer(ZonedDateTime::class.java, KeepMillisecondZonedDateTimeSerializer())
}
mapper.registerModule(javaTimeModule)
return mapper
}
class KeepMillisecondZonedDateTimeSerializer : JsonSerializer<ZonedDateTime>() {
private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
@Throws(IOException::class)
override fun serialize(
value: ZonedDateTime,
jsonGenerator: JsonGenerator,
serializerProvider: SerializerProvider?
) {
jsonGenerator.writeString(formatter.format(value))
}
}
class KeepMillisecondLocalDateTimeSerializer : JsonSerializer<LocalDateTime>() {
private val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
@Throws(IOException::class)
override fun serialize(
value: LocalDateTime,
jsonGenerator: JsonGenerator,
serializerProvider: SerializerProvider?
) {
jsonGenerator.writeString(formatter.format(value))
}
}
}