Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize nested JSON String to Java Object

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.

like image 298
JustM Avatar asked Apr 14 '26 22:04

JustM


1 Answers

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.

like image 189
Andy Brown Avatar answered Apr 16 '26 11:04

Andy Brown



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!