问题描述
我正在编写一种通过SNS HTTP请求处理来自Amazon Simple Email Service的回调的功能.我想将Amazon提供的消息解析为本地对象结构.问题是SNS将JSON消息包装到String中,而Jackson无法对其进行解析.我遇到错误:
I'm coding a functionality of handling callbacks from Amazon Simple Email Service via SNS HTTP requests. I would like to parse message provided by Amazon to local object structure. Problem is that SNS is wrapping JSON message into String and it could not be parsed by Jackson. I'm getting an error:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `xxx.email.domain.aws.ses.Notification` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"notificationType":"Delivery","mail":{"timestamp":"2019-10-02T14:43:14.570Z" ... next values of the message ... }}')
来自SNS的整个消息如下:
Entire message from SNS looks like this one:
{
"Type" : "Notification",
"MessageId" : "4944xxxx-711d-57d4-91b8-8215cxxxxx",
"TopicArn" : "arn:aws:sns:eu-west-1:...",
"Message" : "{\"notificationType\":\"Delivery\",\"mail\":{\"timestamp\":\"2019-10-02T14:43:14.570Z\", ... next values of the message ... },\"delivery\":{\"timestamp\":\"2019-10-02T14:43:16.030Z\", ... next values of the message ... }}",
"Timestamp" : "2019-10-02T14:43:16.062Z",
"SignatureVersion" : "1",
"Signature" : "signature base64",
"SigningCertURL" : "cert url",
"UnsubscribeURL" : "unsubscribe url"
}
我的实际本地结构如下:
My actual local structure looks like this:
@Data
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public class MessageWrapper {
private String type;
private String messageId;
private String topicArn;
private Notification message;
private Date timestamp;
private String signatureVersion;
private String signature;
private String signingCertURL;
private String unsubscribeURL;
}
@Data
public class Notification {
private String notificationType;
private Mail mail;
}
@Data
public class Mail {
private String messageId;
private String source;
private String sourceArn;
private String sourceIp;
private String sendingAccountId;
private String[] destination;
}
我正在寻找一种方法来告诉杰克逊Message
应该从字符串中提取并作为普通JSON处理.
I'm looking for some way to tell Jackson that Message
should be extracted from a String and treated as a normal JSON.
修改
反序列化
private MessageWrapper deserializeMessage(String message) throws IOException {
return new ObjectMapper().readValue(message, MessageWrapper.class);
}
推荐答案
我想解决此问题,您需要为MessageWrapper
类中的Notification
字段以及在MessageWrapper
类中的Mail
字段使用一个自定义反序列化器. Notification
类如下:
I think to solve this you'll need a custom deserializer for Notification
field in MessageWrapper
class as well as one for the Mail
field in the Notification
class the like the following:
public class NotificationDeserializer extends JsonDeserializer<Notification> {
@Override
public Notification deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String text = p.getText();
return new ObjectMapper().readValue(text, Notification.class);
}
}
public class MailDeserializer extends JsonDeserializer<Mail> {
@Override
public Mail deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String text = p.getText();
return new ObjectMapper().readValue(text, Mail.class);
}
}
在类上带有一些注释,如下所示:
With some annotations on your classes like the following:
@Data
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public class MessageWrapper {
private String type;
private String messageId;
private String topicArn;
@JsonDeserialize(using = NotificationDeserializer.class)
private Notification message;
private Date timestamp;
private String signatureVersion;
private String signature;
private String signingCertURL;
private String unsubscribeURL;
}
@Data
public class Notification {
private String notificationType;
@JsonDeserialize(using = MailDeserializer.class)
private Mail mail;
}
@Data
public class Mail {
private String messageId;
private String source;
private String sourceArn;
private String sourceIp;
private String sendingAccountId;
private String[] destination;
}
编辑1
实际上不需要MailDeserializer
.单独使用NotificationDeserializer
即可解决问题.
The MailDeserializer
isn't actually needed. The NotificationDeserializer
alone takes care of the issue.
编辑2
必须在自定义解串器中使用新的ObjectMapper
.
Using a new ObjectMapper
in the custom deserializer is a must.
这篇关于杰克逊反序列化SNS消息错误MismatchedInputException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!