-2

Trying to convert a json string (like below) into a List<String>

"{
"stringField": "abc",
"listField": "[\"item1\", \"item2\", \"item3\"]"
}"

I'm trying to use Jackson ObjectMapper to deserialize a json string. I've created a class representing the above string and am using ObjectMapper readValue to deserialize.


public class Example {

@JsonProperty("stringField")
private String stringField;


@JsonProperty("listField")
private List<String> listField;

}

The stringField gets deserialized fine but the listField keeps giving me this error. Looks like it's getting recognized as a String instead of a list


MismatchedInputExcpetion: Cannot deserialize value of type java.util.ArrayList<String> from String value (token JsonToken.VALUE_STRING)

1 Answer 1

1

Welcome!

The input listeField property looks like a String that is really an embedded JSON array of String objects. This happens. So you need to do further processing of that String property.

You can use a JsonDeserializer that converts a String into a list of strings, and there are many ways to do this. Since in this example, the input string looks suspiciously like an embedded JSON object, you could use another mapper to convert the value to an array, like so:

public class Deserialize {

    static class Example {
        @JsonProperty
        String stringField;

        @JsonProperty()
        @JsonDeserialize(using = JsonStringArrayToSTringList.class)
        List<String> listField;

        @Override
        public String toString() {
            return "Example [stringField=" + stringField + ", listField=" + listField + "]";
        }


    }

    static class JsonStringArrayToSTringList extends JsonDeserializer<List<String>> {
        
        private ObjectMapper m = new ObjectMapper();

        @SuppressWarnings("unchecked")
        @Override
        public List<String> deserialize(JsonParser p, DeserializationContext ctxt)
                throws IOException, JacksonException {
            
            return m.readValue(ctxt.readValue(p, String.class), ArrayList.class);
        }
    }

    public static void main(String[] args) throws Exception {

        String input = "{\n" + "\"stringField\": \"abc\",\n"
                + "\"listField\": \"[\\\"item1\\\", \\\"item2\\\", \\\"item3\\\"]\"\n" + "}";

        var om = new ObjectMapper();

        var c = om.readValue(input, Example.class);

        System.out.println(c);
    }

}

The usage of a new ObjectMapper for each instance of the converter may be costly, so you can probably elaborate on a more efficient way to convert the input string to a list of strings. Hopefully you get the idea.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer! I'm actually very new to Jackson and java as well. Maybe a very basic question but - why does the string need to be converted to a string again? ctxt.readValue(p, String.class) Why can't it directly be converted to a List?
To be converted automatically to a List<String>, listField should look like ["item1", "item2", "item3"], i.e. a JSON array of strings.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.