0

My api response seems like this

{
  "name": "jackson",
  "age": 33,
  "hobby_list": "[{\"name\":\"soccer\", \"priority\":2}, {\"name\":\"game\", \"priority\":1}, {\"name\":\"reading\", \"priority\":3}]"
}

I want to deserialize hobby_list string value as object.

class Person {
  @JsonProperty("name")
  private String name;

  @JsonProperty("age")
  private Integer age;

  @JsonProperty("hobby_list")
  private List<Hobby> hobbyList;
}

class Hobby(
  @JsonProperty("name")
  private String name;

  @JsonProperty("priority")
  private Integer priority;
)

It doesn't work as you know.

Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList<com.joont.domain.Hobby>` out of VALUE_STRING token

What is the best practice to solve the problem?
Annotation? Configure? Custom deserializer?

5
  • How doesn't it work? Is there an error message? Commented Jul 27, 2021 at 1:57
  • @ScaryWombat Yes. I've attached error message above. Commented Jul 27, 2021 at 2:01
  • I guess you should convert your hobby_list to JSON object first, try using JsonNode Commented Jul 27, 2021 at 2:03
  • 3
    The API is defective. If you have any influence, try to get the publisher to fix it. Otherwise, you'll need to double-deserialize that nested JSON. Commented Jul 27, 2021 at 2:04
  • I don't have permission to fix the api. What way I should use to solve this? Maybe hobbyList will be used in many place, I want to implement it common. Commented Jul 27, 2021 at 2:13

1 Answer 1

1

You can convert them by registering custom deserializer as below:

public class PersonDeserializer extends JsonDeserializer<Person> {

    @Override
    public Person deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        ObjectCodec oc = jp.getCodec();
        JsonNode node = oc.readTree(jp);

        final Integer age = node.get("age").asInt();
        final String name = node.get("name").asText();
        final String hobbyListAsString = node.get("hobby_list").asText();

        ObjectMapper mapper = new ObjectMapper();
        // convert JSON array to List of objects
        List<Hobby> hobbyList = Arrays.asList(mapper.readValue(hobbyListAsString, Hobby[].class));

        Person person = new Person();
        person.setName(name);
        person.setAge(age);
        person.setHobbyList(hobbyList);

        return person;
    }
}

and in pojo at root use annotation @JsonDeserialize(using = PersonDeserializer.class) so that above deserializer can be registered. Attaching reference below:

@JsonDeserialize(using = PersonDeserializer.class)
@Data
public class Person {
    @JsonProperty("name")
    private String name;

    @JsonProperty("age")
    private Integer age;

    @JsonProperty("hobby_list")
    private List<Hobby> hobbyList;
}

Then I was able to deserialize above hobby_list string to object

ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue(content, Person.class);
System.out.println(person.getHobbyList());
Sign up to request clarification or add additional context in comments.

Comments

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.