Feature: Inject Values
(see Jira entry JACKSON-406 for details)
Note: as of Jackson 1.9, this feature is only available during Deserialization (reading JSON into POJOs) -- it is possible that similar functionality may be added for serialization in future.
Problem to Solve
Sometimes construction of values requires presence of some contextual information or meta-data, something that is not available from data itself. This may be because a framework requires factories to use, for example. If so, it would be good to have some declarative way to indicate where such values are to be "injected"; as well as have configurable means to provide such Object values.
Solution
Jackson 1.9 adds following thigs:
Annotation @JackonInject (which takes optional String id value) to specify properties for which values are to be injected during deserialization
Mechanisms in ObjectMapper and ObjectReader to specify object -- InjectableValues -- that resolves injectable value id (explicit id, or class name of declared type of value) to value itself; along with a simple implementation (InjectableValues.Std).
Example
Here is a simple example of how to use this feature.
First, a POJO we want to deserialize
public class MyValue
{
@JacksonInject
private Id id;
private NamedValue nameValue;
@JsonCretor
public MyValue(@JacksonInject("factory") NameFactory factory,
@JsonProperty("name") String name) {
nameValue = factory.create(name);
}
}which we could instantiate from JSON like, say:
{ "name" : "some name" }as long as we configured ObjectMapper or ObjectReader like so:
ObjectMapper mapper = new ObjectMapper();
Id id = ...;
NameFactory f = ...;
InjectableValues inject = new InjectableValues.Std()
.addValue(Id.class, id)
.addValue(NameFactory.class, f)
// or create ObjectReader, use 'withInjectables()'
MyValue value = mapper.reader(MyValue.class).withInjectableValues(inject).readValue(json);Notes on above:
- Can inject using all the accessors (field, setter, constructor parameter)
- Injectable values identified either by type (no explicit id), or explicit id; if no explicit id, name of the type class is used as String key
- Injection is done before any data binding; injector gets current bean instance if one exists (as is the case with setters, fields; but not with ctor params)
It is legal to combine @JsonProperty and @JacksonInject; if so, injection is done first, and any value from JSON would override that
- You can fully customize and override injectable value providers, soit should be trivial to write modules to inject Guice or Spring-managed values (Jackson Guice or Jackson Spring ioc modules)
