Home > Mobile >  Deserialize nested JSON String to Java Object
Deserialize nested JSON String to Java Object

Time:12-17

I have JSON looking like this, let say Question

{
    "type": "String",
    "value": "{\"text\":\"Question\",\"type\":\"predefined\",\"parameter\":\"param1\",\"answers\":[\"Answer1\",\"Answer2\",\"Answer3\",\"Answear4\"]}",
    "valueInfo": {}
}

and i want to parse it with Jackson to Question objecti with object Value inside contains details about question (like text, type, and a list of answers)

i try to create classes Question and Value

public class AbasQuestion {
        @JsonProperty("type")
        String type;
        @JsonProperty("value")
        Value value;
        JsonNode valueInfo; 
} 
public class Value {

    String text;
    String type;
    String parameter;
    List<String> answers;
}

and parse string to them with

Question question = objectMapper.readValue(jsonQuestion, Question.class);

but stil i get error

Can not instantiate value of type [simple type, class Value] from String value; no single-String constructor/factory method (through reference chain: Question["value"])

I understan that Value is String and i have to convert it to Value object but how and wher ? inside Value constructor or inside Question setter ? to Jackson could do map it.

CodePudding user response:

You need a custom string-to-value converter. Here's an example using Spring boot as the framework.

@JsonDeserialize(converter = StringToValueConverter.class)
Value value;

If you have a container of Value e.g. List<Value> then it should be contentConverter instead of converter.

Then your converter looks like this.

@Component
public class StringToValueConverter extends StdConverter<String, Value> {

  final ObjectMapper objectMapper;

  public StringToValueConverter(ObjectMapper objectMapper) {
    this.objectMapper = objectMapper;
  }

  @Override
  public Value convert(String value) {
    try {
      return this.objectMapper.readValue(value, Value.class);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
}

You can replace the simple RuntimeException wrapper with something more informative if you need to.

The members of your Value class either need to be public or better provide getter/setters that Jackson can use otherwise all the members will appear to be null after deserialization.

CodePudding user response:

I have not worked enough with Jackson because I did not find it intuitive enough for me, but the JSON Path library did wonders for me. Moreover you can try whatever querry you want to make in online tools before you insert them into your code.

  • Related