With Jackson json library, it is possible to deserialize object through the use of the @JsonCreator
, and be given the "top level" map representing the input json, as follows:
class MyClass {
final int field;
@JsonCreator
public MyClass(Map<String, Object> map) {
this.field = (int) map.get("theInt");
}
}
or even on a static factory method:
class MyClass {
final int field;
public MyClass(int theInt) {
this.field = theInt;
}
@JsonCreator
static MyClass create(Map<String, Object> map) {
return new MyClass((int) map.get("theInt"));
}
}
The previous examples can process the following kind of json input:
{
"key1":"value1",
"key2":"value2",
"key3":"value3"
}
This is particularly useful in my case because I would like to deserialize a json which structure I don't know. Being given access to what I call the "top level map" makes things simple.
I would like to deserialize my objects this way as it also allows to create immutable objects, instead of using @JsonAnySetter
which doesn't permit this, and @JsonProperty
which I can't use as I don't know the properties name in advance as I mentioned earlier.
Then to go further, I would like to inject some configuration in my factory method, and Jackson allows this through the use of @JacksonInject
and a call to withInjectableValues(InjectableValues)
on the ObjectMapper
.
This is eventually the kind of code I would like to use:
class MyClass {
final MyField[] myFields;
public MyClass(MyField... myFields) {
this.myFields = myFields;
}
@JsonCreator
static MyClass create(@JacksonInject("conf") Conf conf, Map<String, Object> map) {
MyFields[] myFields;
// initialize myFields (or any other object) based on the content of map
// and also make use of the inject conf
return new MyClass(myFields);
}
}
Unfortunately, Jackson throws the following kind of exceptions:
JsonMappingException: Argument #1 of constructor [constructor for MyClass, annotations: {JsonCreator=@JsonCreator()}] has no property name annotation; must have name when multiple-paramater constructor annotated as Creator
JsonMappingException: Argument #1 of factory method [method create, annotations: {JsonCreator=@JsonCreator()}] has no property name annotation; must have when multiple-paramater static method annotated as Creator
Does anyone know how I could solve the problem?
To sum up the requirements, I need:
@JsonAnySetter
)@JsonCreator
decorated constructor or factory methodI cannot change the json input format, which looks like this:
{
"key1":"value1",
"key2":"value2",
"key3":"value3"
}
[EDIT]
This is a known issue: http://jira.codehaus.org/browse/JACKSON-711 (not fixed yet)
Right, you would like to both use "delegating" creator (single argument, into which JSON input is first bound) -- different from "property-based" creator where set of named parameters are passed -- and injectable value(s). This should ideally work, but I think it might not work currently. I think there is a Jira entered for this, so you can check it (http://jira.codehaus.org/browse/JACKSON) out.
Just to make sure: are you using version 1.9.2? There have been some fixes in this are since 1.9.0; which at least would give better error message.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With