英文:
Convert Instant to ISO8601 date format not working in Spring Boot
问题
我正在使用Spring Boot 2.3.4.RELEASE,在尝试将包含Instant属性的DTO转换为JSON格式时,jackson ObjectMapper仍然将其转换为时间戳格式,即使已经关闭了write-dates-as-timestamps选项。
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
....
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
application.properties
spring.jackson.serialization.write-dates-as-timestamps = false
DTO:
@Data
public class MyDTO {
Long id;
@NotNull
String number;
@NotNull
Integer year;
@NotNull
VesselContractStatusEnum status;
Instant statusDate;
}
Rest Controller response:
{
"id": 1,
"number": "202000",
"year": 2020,
"status": "Open",
"statusDate": 1602298800
}
根据在StackOverflow中找到的建议,我尝试了以下方法来覆盖ObjectMapper,但没有成功。
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.build();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
JavaTimeModule javaTimeModule = new JavaTimeModule();
objectMapper.registerModule(javaTimeModule);
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
return objectMapper;
}
英文:
I'm using spring boot 2.3.4.RELEASE and when trying to convert a DTO containing an Instant attribute to JSON format, the jackson ObjectMapper keeps converting it to timestamp format, even with write-dates-as-timestamps option turned off.
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
....
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
application.properties
spring.jackson.serialization.write-dates-as-timestamps = false
DTO:
@Data
public class MyDTO {
Long id;
@NotNull
String number;
@NotNull
Integer year;
@NotNull
VesselContractStatusEnum status;
Instant statusDate;
}
Rest Controller response:
{
"id": 1,
"number": "202000",
"year": 2020,
"status": "Open",
"statusDate": 1602298800
}
Following recommendations found here in StackOverflow, I tried to override the ObjectMapper using the follwoing approach, but it didn't work.
@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.build();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
JavaTimeModule javaTimeModule = new JavaTimeModule();
objectMapper.registerModule(javaTimeModule);
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
return objectMapper;
}
答案1
得分: 1
Instant.toString()
返回ISO8601格式的字符串(尽其所值)。也许为Json字段提供一个getter会有帮助?
英文:
Instant.toString()
returns the ISO8601 formatted string (for what its worth). Perhaps providing a getter for the Json field would help?
答案2
得分: 1
你需要按照以下方式编写自定义的序列化器和反序列化器类:
序列化器类:
public class InstantSerializer extends JsonSerializer<Instant> {
private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC);
@Override
public void serialize(Instant instant, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
String str = dateTimeFormatter.format(instant);
jsonGenerator.writeString(str);
}
}
反序列化器类:
public class InstantDeserializer extends JsonDeserializer<Instant> {
private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC);
@Override
public Instant deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
return Instant.from(dateTimeFormatter.parse(jsonParser.getText()));
}
}
然后在你的 DTO 类中的 Instant 变量上方添加以下注解:
@JsonDeserialize(using = InstantDeserializer.class)
@JsonSerialize(using = InstantSerializer.class)
Instant statusDate;
英文:
You have to write a Custom Serializer and De Serializer classes as below:
Serializer Class:
public class InstantSerializer extends JsonSerializer<Instant> {
private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC);
@Override
public void serialize(Instant instant, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
String str = dateTimeFormatter.format(instant);
jsonGenerator.writeString(str);
}
}
Deserializer Class:
public class InstantDeserializer extends JsonDeserializer<Instant> {
private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC);
@Override
public Instant deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
return Instant.from(dateTimeFormatter.parse(jsonParser.getText()));
}
}
Then add the below annotations on top of the Instant variable in your DTO class as below:
@JsonDeserialize(using = InstantDeserializer.class)
@JsonSerialize(using = InstantSerializer.class)
Instant statusDate;
答案3
得分: 1
你是否在任何地方使用了注解
@EnableWebMvc
经过尝试了各种方法仍然没有成功,我通过移除我在主类上(使用 @SpringBootApplication 注解)的 @EnableWebMvc 注解使其工作起来。
我认为 @EnableWebMvc 接管了所有的 MVC 配置控制。
如果你真的需要 @EnableWebMvc,那么你必须手动注册序列化器/反序列化器。
例如,通过将类似下面这样的内容添加到主类上(使用 @SpringBootApplication 注解):
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
{
SimpleModule m = new SimpleModule();
m.addSerializer(Instant.class, new MyCustomJsonSerializer());
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder().modules(m);
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
英文:
Do you have annotation
@EnableWebMvc
anywhere?
After having tried everything without success, I got it to work by removing the @EnableWebMvc annotation I had on the main class (annotated with @SpringBootApplication).
I think @EnableWebMvc takes over all MVC configuration control.
If you really need @EnableWebMvc, then you have to register the serializer / deserializer by hand.
Eg. by adding something like this to the main class (annotated with @SpringBootApplication):
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
{
SimpleModule m = new SimpleModule();
m.addSerializer(Instant.class, new MyCustomJsonSerializer());
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder().modules(m);
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论