英文:
Could not read JSON: Cannot construct instance of `java.time.ZonedDateTime` (no Creators, like default construct, exist)
问题
我有一个监听队列并将其映射到POJO的服务。但是,即使设置了ObjectMapper的@Configuration,我仍然不断收到以下错误:
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.registerModule(new JavaTimeModule());
return mapper;
}
我的POJO:
public class ResultDto {
private ZonedDateTime dateSent;
private ZonedDateTime dateDeliveryReceiptReceived;
public ResultDto() {}
}
我收到以下错误:
Caused by: org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Cannot construct instance of `java.time.ZonedDateTime` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('2020-08-03T11:02:51.044+0000')
提前致谢!
英文:
I have a service that listens to a queue then maps it to a POJO.
But I'm always getting this error even after setting the @Configuration
of ObjectMapper
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.registerModule(new JavaTimeModule());
return mapper;
}
My POJO:
public class ResultDto {
private ZonedDateTime dateSent;
private ZonedDateTime dateDeliveryReceiptReceived;
public ResultDto() {}
}
I get this error:
Caused by: org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Cannot construct instance of `java.time.ZonedDateTime` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('2020-08-03T11:02:51.044+0000')
Thanks in advance!
答案1
得分: 1
使用@JsonFormat(pattern = '在此指定格式')
,ObjectMapper 默认尝试在构造函数中创建 ZonedDateTime 对象,但这种对象不存在。通过添加此注解,您将允许它使用指定的格式从字符串中解析它。
英文:
Use
@JsonFormat(pattern = 'specify pattern here')
ObjectMapper by default tries to create ZonedDateTime object with String in constructor and such thing does not exists. By adding this annotation you will allow it to parse it from String using given format.
答案2
得分: 1
From the error, it looks like it is looking for a String
-argument constructor. Try after adding the following constructors in ResultDto
:
public ResultDto(ZonedDateTime dateSent, ZonedDateTime dateDeliveryReceiptReceived) {
this.dateSent = dateSent;
this.dateDeliveryReceiptReceived = dateDeliveryReceiptReceived;
}
public ResultDto(String dateSent, String dateDeliveryReceiptReceived) {
this.dateSent = ZonedDateTime.parse(dateSent, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
this.dateDeliveryReceiptReceived = ZonedDateTime.parse(dateDeliveryReceiptReceived, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
}
英文:
From the error, it looks like it is looking for String
-argument constructor. Try after adding the following constructors in ResultDto
:
public ResultDto(ZonedDateTime dateSent, ZonedDateTime dateDeliveryReceiptReceived) {
this.dateSent = dateSent;
this.dateDeliveryReceiptReceived = dateDeliveryReceiptReceived;
}
public ResultDto(String dateSent, String dateDeliveryReceiptReceived) {
this.dateSent = ZonedDateTime.parse(dateSent, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
this.dateDeliveryReceiptReceived = ZonedDateTime.parse(dateDeliveryReceiptReceived,
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
}
答案3
得分: 1
感谢那些回答的人。
在队友的帮助下,我们发现Spring Cloud有自己的对象映射器,而不是直接使用ObjectMapper
。由于这个DTO/POJO是用于处理来自AWS SNS/SQS的消息,应该这样做:
@Bean
public MappingJackson2MessageConverter mappingJackson2MessageConverter(ObjectMapper objectMapper) {
MappingJackson2MessageConverter jacksonMessageConverter = new MappingJackson2MessageConverter();
jacksonMessageConverter.setObjectMapper(objectMapper);
jacksonMessageConverter.setSerializedPayloadClass(String.class);
jacksonMessageConverter.setStrictContentTypeMatch(true);
return jacksonMessageConverter;
}
英文:
Thanks for those who answered.
With the help of team mate, we discovered that the spring cloud has its own object mapper. And not the ObjectMapper
directly. Since this DTO/POJO is to the message from a AWS SNS/SQS.
This should do:
@Bean
public MappingJackson2MessageConverter mappingJackson2MessageConverter(ObjectMapper objectMapper) {
MappingJackson2MessageConverter jacksonMessageConverter = new MappingJackson2MessageConverter();
jacksonMessageConverter.setObjectMapper(objectMapper);
jacksonMessageConverter.setSerializedPayloadClass(String.class);
jacksonMessageConverter.setStrictContentTypeMatch(true);
return jacksonMessageConverter;
}
答案4
得分: 0
我们在使用Java 8、Spring Boot和AWS SQS时遇到了相同的问题。我们创建了一个自定义的反序列化器,它扩展自InstantDeserializer以处理ZonedDateTime。我们直接将自定义反序列化器应用于与SQS消息关联的DTO。
import com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class CustomZonedDateTimeDeserializer extends InstantDeserializer<ZonedDateTime> {
public CustomZonedDateTimeDeserializer() {
super(ZonedDateTime.class,
DateTimeFormatter.ISO_ZONED_DATE_TIME,
ZonedDateTime::from,
a -> ZonedDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId.getId().equals("UTC") ? ZoneOffset.UTC : a.zoneId),
a -> ZonedDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId.getId().equals("UTC") ? ZoneOffset.UTC : a.zoneId),
ZonedDateTime::withZoneSameInstant, false);
}
}
在DTO中,我们会有:
public class ResultDto {
@JsonDeserialize(using = CustomZonedDateTimeDeserializer.class)
private ZonedDateTime dateSent;
@JsonDeserialize(using = CustomZonedDateTimeDeserializer.class)
private ZonedDateTime dateDeliveryReceiptReceived;
public ResultDto() {}
}
英文:
We face the same problem by using java 8, Springboot and AWS SQS. We create a custom deserializer which extends from InstantDeserializer for a ZonedDateTime. We apply the custom deserializer directly on the DTO which is associated to the SQS message.
import com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class CustomZonedDateTimeDeserializer extends InstantDeserializer<ZonedDateTime> {
public CustomZonedDateTimeDeserializer() {
super(ZonedDateTime.class,
DateTimeFormatter.ISO_ZONED_DATE_TIME,
ZonedDateTime::from,
a -> ZonedDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId.getId().equals("UTC") ? ZoneOffset.UTC : a.zoneId),
a -> ZonedDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId.getId().equals("UTC") ? ZoneOffset.UTC : a.zoneId),
ZonedDateTime::withZoneSameInstant, false);
}
}
In the DTO, we will have:
public class ResultDto {
@JsonDeserialize(using = CustomZonedDateTimeDeserializer.class)
private ZonedDateTime dateSent;
@JsonDeserialize(using = CustomZonedDateTimeDeserializer.class)
private ZonedDateTime dateDeliveryReceiptReceived;
public ResultDto() {}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论