Note that there are some explanatory texts on larger screens.

plurals
  1. POUse @JacksonInject with @JsonCreator on a top level map
    text
    copied!<p>With Jackson json library, it is possible to deserialize object through the use of the <code>@JsonCreator</code>, and be given the "top level" map representing the input json, as follows:</p> <pre class="lang-java prettyprint-override"><code>class MyClass { final int field; @JsonCreator public MyClass(Map&lt;String, Object&gt; map) { this.field = (int) map.get("theInt"); } } </code></pre> <p>or even on a static factory method:</p> <pre class="lang-java prettyprint-override"><code>class MyClass { final int field; public MyClass(int theInt) { this.field = theInt; } @JsonCreator static MyClass create(Map&lt;String, Object&gt; map) { return new MyClass((int) map.get("theInt")); } } </code></pre> <p>The previous examples can process the following kind of json input:</p> <pre class="lang-json prettyprint-override"><code>{ "key1":"value1", "key2":"value2", "key3":"value3" } </code></pre> <p>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.</p> <p>I would like to deserialize my objects this way as it also allows to create immutable objects, instead of using <code>@JsonAnySetter</code> which doesn't permit this, and <code>@JsonProperty</code> which I can't use as I don't know the properties name in advance as I mentioned earlier.</p> <p>Then to go further, I would like to inject some configuration in my factory method, and Jackson allows this through the use of <code>@JacksonInject</code> and a call to <code>withInjectableValues(InjectableValues)</code> on the <code>ObjectMapper</code>.</p> <p>This is eventually the kind of code I would like to use:</p> <pre class="lang-java prettyprint-override"><code>class MyClass { final MyField[] myFields; public MyClass(MyField... myFields) { this.myFields = myFields; } @JsonCreator static MyClass create(@JacksonInject("conf") Conf conf, Map&lt;String, Object&gt; 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); } } </code></pre> <p>Unfortunately, Jackson throws the following kind of exceptions:</p> <ul> <li>when trying the trick on the constructor</li> </ul> <p><code>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</code></p> <ul> <li>when trying the trick on the factory method</li> </ul> <p><code>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</code></p> <p>Does anyone know how I could solve the problem?</p> <p>To sum up the requirements, I need:</p> <ul> <li>access to the top level map (don't know the json property names in advance)</li> <li>to create an immutable object (so can't use <code>@JsonAnySetter</code>)</li> <li>to inject some conf to the <code>@JsonCreator</code> decorated constructor or factory method</li> </ul> <p>I cannot change the json input format, which looks like this:</p> <pre class="lang-json prettyprint-override"><code>{ "key1":"value1", "key2":"value2", "key3":"value3" } </code></pre> <p>[EDIT]</p> <p>This is a known issue: <a href="http://jira.codehaus.org/browse/JACKSON-711" rel="noreferrer">http://jira.codehaus.org/browse/JACKSON-711</a> (not fixed yet)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload