Search code examples
javajsonspringdeserialization

Spring JSON to Map Deserialization Failing


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?


Solution

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