I am trying to use Spring to deserialize incoming JSON objects. I have the following class:
public class ContentRequestMessage {
private String type;
private String messageId;
private String topicArn;
/**
* Message contents:
*
* "Message" : "{"location": "/interactments/d2734-9304cceb7c3a", "status": "draft_created"}"
*/
private Map<String, Object> message;
private Date timestamp;
private String signatureVersion;
private String signature;
private String signingCertURL;
private String unsubscribeURL;
private Map<String, Object> messageAttributes;
//constructors, getters & setters
}
I am trying to feed the following JSON request:
{
"type" : "Notification",
"messageId" : "b2b769284",
"topicArn" : "arn:aws:sn",
"message" : "{\"location\": \"/interacments/d275d0-893ceb7c3a\", \"status\": \"draft_created\"}",
"timestamp" : "2023-01-03T11:17:29.537Z",
"signatureVersion" : "1",
"signature" : "1Jag1w==",
"signingCertURL" : "https://2625d385.pem",
"unsubscribeURL" : "httbscri2b1f502953",
"messageAttributes" : {
"scope" : {"Type":"String","Value":"nas_consumer"}
}
}
Into my controller:
@RestController
public class TestController {
@PostMapping
public void postRequest(@RequestBody ContentRequestMessage contentRequestMessage) {
System.out.println(contentRequestMessage);
}
}
But I am encountering the following error:
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `java.util.LinkedHashMap` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"location": "/interactments/d2734-9304cceb7c3a", "status": "draft_created"}')
Other threads discuss using an ObjectMapper and Jackson, but I want to rely on Spring to deserialize this object for me. What is going wrong here?
CodePudding user response:
Your message
is not a map, but a simple String
.
The content of messageAttributes.scope
itself is a map again, and not an Object
.
Try this:
public class ContentRequestMessage {
private String type;
private String messageId;
private String topicArn;
private String message;
private Date timestamp;
private String signatureVersion;
private String signature;
private String signingCertURL;
private String unsubscribeURL;
private Map<String, Map<String, String>> messageAttributes;
// rest of implementation
}
CodePudding user response:
im a newcomer to StackOverflow
From your question, it seems to have a problem of serialize.
I guess you want to convert to this type:
message.get(location); // "/interacments/d275d0-893ceb7c3a"
message.get(status); // "draft_created"
But on your JSON request
:
{
"type" : "Notification",
"messageId" : "b2b769284",
"topicArn" : "arn:aws:sn",
"message" : "
{\"location\": \"/interacments/d275d0-893ceb7c3a\",
\"status\": \"draft_created\"
}",
"timestamp" : "2023-01-03T11:17:29.537Z",
"signatureVersion" : "1",
"signature" : "1Jag1w==",
"signingCertURL" : "https://2625d385.pem",
"unsubscribeURL" : "httbscri2b1f502953",
"messageAttributes" : {
"scope" : {"Type":"String","Value":"nas_consumer"}
}
}
The field name messageAttributes
is same of message
, so why the messageAttributes
not throw exception?
From the JSON perspective , the field message
provides the String, messageAttributes
provides the Map.
So this real problem is spring cannot deserialize String to Map.
{
"message" : {
"location": "interacments/d275d0-893ceb7c3a",
"status": "draft_created"
}
}