1

I'm trying to convert the next string:

"{ \"contacts\": [{\"name\":\"1\",\"phone\":\"+123456\"}]}"

to some Custom object:

public class CustomObject{

    private List<Contact> contacts;

    public CustomObject(){

    }

    public CustomObject(List<Contact> contacts) {
        this.contacts = contacts;
    }

    public List<Contact> getContactList() {
        return contacts;
    }

    public void setContactList(List<Contact> contacts) {
        this.contacts = contacts;
    }
}

In addition, there is another object within this CustomObject:

public class Contact {

    private String name;
    private String phone;

    public Contact() {
    }

    public Contact(String name, String phone) {
        this.name = name;
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

Right now, I'm trying to do the following:

private List<Contact> parseString(String jsonAsString) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    CustomObject customObject = mapper.readValue(jsonAsString, CustomObject .class);
    return customObject .getContactList();
}

But I'm getting the next error:

com.fasterxml.jackson.databind.exc.MismatchedInputException: No content to map due to end-of-input
 at [Source: (String)""{ \"contacts\": [{\"name\":\"1\",\"phone\":\"+972545519713\"}]}""; line: 1, column: 1]
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Roni Koren Kurtberg
  • 495
  • 1
  • 8
  • 18

1 Answers1

7

Jackson is clever, but not that clever.

Your public setter setContactList cannot be recognized during de-serialization without an annotation.

You have two choices:

  1. Annotate it with @JsonProperty("contacts")
  2. Change it to setContacts

Other choices would include changing your JSON or making the actual fields accessible - not elaborating as they would very likely be bad choices.

Also consider revising your code in other places, e.g. for the getContactList getter if you plan on serializing instances of your POJO.

Mena
  • 47,782
  • 11
  • 87
  • 106
  • Or change the the field name to contactList (that is least visible change), but I think #2 is long term the best -- the field w/get/set is best named contacts to show it is a collection, rather than what kind of collection (List), though with JSON deserializtion having an idea of the expected type might be more useful than hiding implementation details. Yeah, this gets complicated. – Kristian H Apr 13 '18 at 13:06
  • 1
    @KristianH unfortunately changing the field name would also imply changing the JSON! – Mena Apr 13 '18 at 13:07
  • Hey @mena, first of all, thanks for your time and answer. Unfforntunetly, this didn't work out. Still getting the same error: "Cannot construct instance of `com.ronikurtberg.Utils.CustomObject` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{ "contacts": [{"name":"0","phone":"+123456"}]}') at [Source: (String)""{ \"contacts\": [{\"name\":\"0\",\"phone\":\"+123456\"}]}""; line: 1, column: 1]". The new setter: `public void setContacts(List contacts) { this.contacts = contacts; }` – Roni Koren Kurtberg Apr 13 '18 at 13:14
  • Hi @RoniKurtberg, I did test my answer against your MCVE (and I invite you to try too). I suspect there may be some additional code you didn't post for brevity that's somehow interfering here - e.g. not sure what `MobileResponse` is doing... – Mena Apr 13 '18 at 13:17
  • @Mena - the input is: `"{ \"contacts\": [{\"name\":\"0\",\"phone\":\"+123456\"}]}"`. And I've changed only the setter name as you said. Maybe the string is Illegal? – Roni Koren Kurtberg Apr 13 '18 at 13:20
  • 1
    @RoniKurtberg nah, I've literally copypasted the `String` from your question to test my code. However, if you look closer, the error messages are different, which suggests you may be having trouble in another part of your code, maybe with another payload. Take a look at [this](https://stackoverflow.com/questions/45110371/no-string-argument-constructor-factory-method-to-deserialize-from-string-value) SO post about your new error message. – Mena Apr 13 '18 at 13:22
  • @Mena - You are right, this is a different error. I saw the solution there, but why using `mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);` - Where do I have an empty string? Trying to understand this solution against my string. Thanks again. – Roni Koren Kurtberg Apr 13 '18 at 13:25
  • @RoniKurtberg "where do I have an empty string?" --> clearly not in the JSON you display in your question. Try debugging your code, you're probably parsing something else as well... – Mena Apr 13 '18 at 13:26
  • @Mena - I understand you, but this is the string that the mapper gets: `"{ \"contacts\": [{\"name\":\"0\",\"phone\":\"+123456\"}]}"`. And this is the error cause: `com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of com.ronikurtberg.Utils.CustomObject (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{ "contacts": [{"name":"0","phone":"+123456"}]}') at [Source: (String)""{ \"contacts\": [{\"name\":\"0\",\"phone\":\"+123456\"}]}""; line: 1, column: 1]` - Maybe this is invalid string? – Roni Koren Kurtberg Apr 13 '18 at 13:32
  • @RoniKurtberg unfortunately there's little I can help with considering your currently posted code works with my suggestion. I'd recommend you make sure your actual code matches what you posted, including the `ObjectMapper` configuration, or other parts of your code that you haven't posted. – Mena Apr 13 '18 at 13:42