- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在编写一项功能,通过 SNS HTTP 请求处理来自 Amazon Simple Email Service 的回调。我想将亚马逊提供的消息解析为本地对象结构。问题是 SNS 将 JSON 消息包装成字符串,而 Jackson 无法解析它。我收到一个错误:
com.fasterxml.jackson.databind.exc.MismatchedInputException:无法构造 `xxx.email.domain.aws.ses.Notification` 的实例(尽管至少存在一个 Creator):没有字符串参数构造函数/从字符串值反序列化的工厂方法 ('{"notificationType":"Delivery","mail":{"timestamp":"2019-10-02T14:43:14.570Z"... 消息的下一个值 ... }}')
来自 SNS 的整个消息如下所示:
{
"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"
}
我的实际本地结构如下所示:
@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;
}
我正在寻找某种方式来告诉 Jackson Message
应该从字符串中提取并作为普通 JSON 处理。
编辑
反序列化
private MessageWrapper deserializeMessage(String message) throws IOException {
return new ObjectMapper().readValue(message, MessageWrapper.class);
}
最佳答案
我认为要解决这个问题,您需要为 MessageWrapper
类中的 Notification
字段和 Mail
字段自定义反序列化器在 Notification
类中,如下所示:
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);
}
}
在你的类上添加一些注释,如下所示:
@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
单独处理这个问题。
编辑 2
必须在自定义反序列化器中使用新的 ObjectMapper
。
关于java - Jackson反序列化SNS消息报错MismatchedInputException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58204267/
我无法在附加行中显示“真”、“假”、"is"和“否”按钮。 我在这里有一个应用程序:Application 请按照以下步骤使用应用程序: 1。当你打开应用程序时,你会看到一个绿色的加号按钮,点击 在此
我是一名优秀的程序员,十分优秀!