I have the following JSON:
{
"some_key": "{\"a\": 1, \"b\": \"text\"}"
}
As you can see some_key field is not a JSON object it is a string, that contains valid JSON.
I would like to parse it into following structure:
class Foo {
Bar some_key;
}
class Bar {
int a;
String b;
}
UPDATE:
class A and B, has getters and setters, constructors. I haven't show them to keep sample short and simple.
I can't edit the weird structure of the JSON.
The question is how to ask Jackson parse the inner string field as JSON object.
@t_liang is very close - just need a bit more room than a comment to show the working example...
With:
class Foo {
@JsonDeserialize(using = BarDeserializer.class)
private Bar some_key;
}
Then the current ObjectMapper is actually the JsonParser.getCodec():
public class BarDeserializer extends JsonDeserializer<Bar> {
@Override
public Bar deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String text = p.getText();
ObjectMapper mapper = (ObjectMapper) p.getCodec();
return mapper.readValue(text, Bar.class);
}
}
Then this...
ObjectMapper mapper = new ObjectMapper();
Foo foo = mapper.readValue(
"{ \"some_key\": \"{\\\"a\\\": 1, \\\"b\\\": \\\"text\\\"}\" }",
Foo.class);
System.out.println(foo.getSome_key());
... shows the expected value:
Bar [a=1, b=text]
step 1:
public class BarDeserializer extends JsonDeserializer<Bar> {
@Override
public Bar deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String text = p.getText();
return <your ObjectMapper>.readValue(text, Bar.class);
}
}
step 2:
class Foo {
@JsonDeserialize(using=BarDeserializer.class)
Bar some_key;
}
or
@JsonDeserialize(using=BarDeserializer.class)
class Bar {
int a;
String b;
}
There are a couple of problems:
json provided in example does not correspond to the schema. E.g. as per json, some_key is a String field (it's wrapped in double quotes) whereas as per schema, it's a Boo field. You need to change json to look like following (Or change some_value to String type):
{
"some_key": {\"a\": 1, \"b\": \"text\"}
}
There are no getters or setters. Jackson can't deserialize can't access getters/setters via reflection.
Here's the working example:
class Foo {
Bar some_key;
public Bar getSome_key() {
return some_key;
}
public void setSome_key(Bar some_key) {
this.some_key = some_key;
}
}
class Bar {
int a;
String b;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
}
Deserialization:
ObjectMapper mapper = new ObjectMapper();
Foo response = mapper.readValue("{\"some_key\": {\"a\": 1, \"b\": \"text\"}}", Foo.class);