Home > Blockchain >  Spring JSON to Map Deserialization Failing
Spring JSON to Map Deserialization Failing

Time:01-05

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"
          }
 }
  • Related