Jackson , java.time , ISO 8601 , 无毫秒序列化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40487656/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hymanson , java.time , ISO 8601 , serialize without milliseconds
提问by Benjamin M
I'm using Hymanson 2.8 and need to communicate with an API that doesn't allow milliseconds within ISO 8601 timestamps.
我正在使用 Hymanson 2.8 并且需要与一个不允许在 ISO 8601 时间戳内出现毫秒的 API 进行通信。
The expected format is this: "2016-12-24T00:00:00Z"
预期的格式是这样的: "2016-12-24T00:00:00Z"
I'm using Hymanson's JavaTimeModule with WRITE_DATES_AS_TIMESTAMPS
set to false
.
我正在使用 Hymanson 的 JavaTimeModule 并WRITE_DATES_AS_TIMESTAMPS
设置为false
.
But this will print milliseconds.
但这将打印毫秒。
So I tried to use objectMapper.setDateFormat
which didn't change anything.
所以我尝试使用objectMapper.setDateFormat
它并没有改变任何东西。
My current workaround is this:
我目前的解决方法是这样的:
ObjectMapper om = new ObjectMapper();
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendInstant(0)
.toFormatter();
JavaTimeModule jtm = new JavaTimeModule();
jtm.addSerializer(Instant.class, new JsonSerializer<Instant>() {
@Override
public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
gen.writeString(dtf.format(value));
}
});
om.registerModule(jtm);
I'm overriding the default serializer for Instant.class
which works.
我正在覆盖适用的默认序列化程序Instant.class
。
Is there any nice way using some configuration parameter to solve this?
有什么好的方法可以使用一些配置参数来解决这个问题吗?
采纳答案by Pau
Update:
更新:
Just add a @JsonFormat
annotation whith the date format above the Instant
property. It's very easy.
只需@JsonFormat
在Instant
属性上方添加带有日期格式的注释即可。这很容易。
In the case you have an ObjectMapper with the JavaTimeModule
like next:
如果您有一个 ObjectMapper,如下JavaTimeModule
所示:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
If you have a class with an Instant
property, you should add the @JsonFormat
annotation and put the date pattern which hasn't milliseconds. It would be like next:
如果你有一个带有Instant
属性的类,你应该添加@JsonFormat
注释并放置没有毫秒的日期模式。它会像下一个:
public static class TestDate {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss", timezone = "UTC")
Instant instant;
//getters & setters
}
So if you serialize an object to Json it works perfectly:
因此,如果您将对象序列化为 Json,它可以完美运行:
String json = mapper.writeValueAsString(testDate);
System.out.println(json);
Output
输出
{"instant":"2016-11-10 06:03:06"}
{“即时”:“2016-11-10 06:03:06”}
Old Answer. I don't know why but It doesn't work propertly:
旧答案。我不知道为什么,但它不能正常工作:
You could use the Hymanson2ObjectMapperBuilder
to build it.
您可以使用Hymanson2ObjectMapperBuilder
来构建它。
You just need to add the dateFormat you want. It would be something like next:
您只需要添加所需的 dateFormat。接下来是这样的:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
ObjectMapper mapper = Hymanson2ObjectMapperBuilder
.json()
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.modules(new JavaTimeModule())
.dateFormat(dateFormat)
.build();
回答by Sagar Veeram
Here is an alternative which is something you can set globally, but will need you to use ZonedDateTime
with instant formatter as we can't set the format for the Instant
Serializer provided with Java Time Module.
这是您可以全局设置的替代方法,但需要您ZonedDateTime
与即时格式化程序一起使用,因为我们无法为Instant
Java 时间模块提供的序列化程序设置格式。
You wont see any side effects of using zoned date time for instant as Hymanson serializes the zone id separately and is disabled by default. So technically, this is similar to applying the formatter to Instant
.
您不会看到立即使用分区日期时间的任何副作用,因为 Hymanson 单独序列化区域 ID 并且默认情况下禁用。所以从技术上讲,这类似于将格式化程序应用于Instant
.
When used this way, the ZonedDateTime
serializer delegates the serialization to InstantBaseSerializer
and uses the specified custom format.
以这种方式使用时,ZonedDateTime
序列化程序将序列化委托给InstantBaseSerializer
并使用指定的自定义格式。
@RunWith(JUnit4.class)
public class InstantNoMillisTest {
private ObjectMapper objectMapper;
@Before
public void init() {
JavaTimeModule module = new JavaTimeModule();
ZonedDateTimeSerializer zonedDateTimeSerializer = new ZonedDateTimeSerializer(new DateTimeFormatterBuilder().appendInstant(0).toFormatter());
module.addSerializer(ZonedDateTime.class, zonedDateTimeSerializer);
module.addDeserializer(ZonedDateTime.class, InstantDeserializer.ZONED_DATE_TIME);
objectMapper = Hymanson2ObjectMapperBuilder.json()
.modules(module)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
}
@Test
public void serialize() throws IOException {
ZonedDateTime zonedDateTime = ZonedDateTime.now();
String noMillis = objectMapper.writeValueAsString(zonedDateTime);
System.out.print(noMillis);
}
@Test
public void deserialize() throws IOException {
String dateTime = "\"2017-10-26T12:54:59Z\"";
ZonedDateTime noMillis = objectMapper.readValue(dateTime, ZonedDateTime.class);
System.out.print(noMillis);
}
}
回答by ZZ 5
Here's some Kotlin code of formatting Instant
fields, so they will not contain milliseconds, you can use custom date formatters
这是格式化Instant
字段的一些 Kotlin 代码,因此它们不会包含毫秒,您可以使用自定义日期格式化程序
ObjectMapper().apply {
val javaTimeModule = JavaTimeModule()
javaTimeModule.addSerializer(Instant::class.java, Iso8601WithoutMillisInstantSerializer())
registerModule(javaTimeModule)
disable(WRITE_DATES_AS_TIMESTAMPS)
}
private class Iso8601WithoutMillisInstantSerializer
: InstantSerializer(InstantSerializer.INSTANCE, false, DateTimeFormatterBuilder().appendInstant(0).toFormatter())