JsonMappingException: no single-String constructor/factory method

6.6k views Asked by At

[This is not a duplicate of Can not instantiate value of type from JSON String; no single-String constructor/factory method: that is a far simpler POJO and JSON. The solution in my case was different as well.]

The JSON I want to parse and create a POJO from:

{
    "test_mode": true,
    "balance": 1005,
    "batch_id": 99,
    "cost": 1,
    "num_messages": 1,
    "message": {
        "num_parts": 1,
        "sender": "EXAMPL",
        "content": "Some text"
    },
    "receipt_url": "",
    "custom": "",
    "messages": [{
        "id": 1,
        "recipient": 911234567890
    }],
    "status": "success"
}

If the response happens to be an error, it looks like:

{
    "errors": [{
        "code": 80,
        "message": "Invalid template"
    }],
    "status": "failure"
}

Here's the POJO I have defined:

@Data
@Accessors(chain = true)
public class SmsResponse {

    @JsonProperty(value = "test_mode")
    private boolean testMode;

    private int balance;

    @JsonProperty(value = "batch_id")
    private int batchId;

    private int cost;

    @JsonProperty(value = "num_messages")
    private int numMessages;

    private Message message;

    @JsonProperty(value = "receipt_url")
    private String receiptUrl;

    private String custom;

    private List<SentMessage> messages;

    private String status;

    private List<Error> errors;

    @Data
    @Accessors(chain = true)
    public static class Message {

        @JsonProperty(value = "num_parts")
        private int numParts;

        private String sender;

        private String content;
    }

    @Data
    @Accessors(chain = true)
    public static class SentMessage {

        private int id;

        private long recipient;
    }

    @Data
    @Accessors(chain = true)
    public static class Error {

        private int code;

        private String message;
    }

}

The annotations @Data (tells Lombok to automatically generate getters, setters, toString() and hashCode() methods for the class) and @Accessors (tells Lombok to generate the setters in such a way that they can be chained) are from Project Lombok.

Seems like a straightforward setup, but every time I run:

objectMapper.convertValue(response, SmsResponse.class);

I get the error message:

Can not instantiate value of type [simple type, class com.example.json.SmsResponse]
from String value ... ; no single-String constructor/factory method

Why do I need a single-string constructor for SmsResponse, and if so, which string do I accept in it?

1

There are 1 answers

1
Phoenix On BEST ANSWER

To parse and map a JSON String with ObjectMapper you need to use the readValue method:

objectMapper.readValue(response, SmsResponse.class);