Note that there are some explanatory texts on larger screens.

plurals
  1. PODeserialize JSON object/map as generic Collection with Jackson
    primarykey
    data
    text
    <p>I have JSON maps like this:</p> <pre><code>"things": {"foo": {"name": "foo", ...}, "bar": {"name": "bar", ...}} </code></pre> <p>I want to deserialize them as if they were arrays:</p> <pre><code>"things": [{"name": "foo", ...}, {"name": "bar", ...}] </code></pre> <p>(to match XML/JAXB deserialization behavior):</p> <pre><code>&lt;things&gt;&lt;thing name="foo"&gt;...&lt;/thing&gt;&lt;thing name="bar"&gt;...&lt;/thing&gt;&lt;/things&gt; </code></pre> <p>into a collection such as this:</p> <pre><code>@XmlElementWrapper @XmlElement(name = "thing") @JsonDeserialize(using = MapToCollectionDeserializer.class) Collection&lt;Thing&gt; things; </code></pre> <p>Note that I have collections with various element types -- not just <code>Thing</code> -- so I need a generic mechanism.</p> <p>However, when writing a custom deserializer, what's the right way to access the type information of the context?</p> <pre><code>public class MapToCollectionDeserializer extends StdDeserializer&lt;Object&gt; { @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { Preconditions.checkState(jp.getCurrentToken() == JsonToken.START_OBJECT); final LinkedList&lt;Object&gt; result = new LinkedList&lt;&gt;(); JsonToken tok; while ((tok = jp.nextToken()) != JsonToken.END_OBJECT) { Preconditions.checkState(tok == JsonToken.FIELD_NAME); // How to get the collection element type for deserialization? result.add(...); } return result; } } </code></pre> <p>My approach so far is using <code>ContextualDeserializer</code>, which can provide a <code>BeanProperty</code> (which contains type information) to the deserializer. However, a JsonDeserializer must still have a no-arg constructor, so I end up constructing a broken object at first:</p> <pre><code>public class MapToCollectionDeserializer extends StdDeserializer&lt;Object&gt; implements ContextualDeserializer&lt;Object&gt; { private final BeanProperty property; public MapToCollectionDeserializer() { super(Collection.class); property = null; // YUCK: BROKEN!!! } private MapToCollectionDeserializer(BeanProperty property) { super(property.getType()); this.property = property; } @Override public JsonDeserializer&lt;Object&gt; createContextual(DeserializationConfig config, BeanProperty property) throws JsonMappingException { return new MapToCollectionDeserializer(property); } @Override public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { Preconditions.checkState(jp.getCurrentToken() == JsonToken.START_OBJECT); final JavaType elementType = property.getType().containedType(0); final LinkedList&lt;Object&gt; result = new LinkedList&lt;&gt;(); JsonToken tok; while ((tok = jp.nextToken()) != JsonToken.END_OBJECT) { Preconditions.checkState(tok == JsonToken.FIELD_NAME); jp.nextToken(); final JsonDeserializer&lt;Object&gt; valueDeser = ctxt.getDeserializerProvider() .findValueDeserializer(ctxt.getConfig(), elementType, property); result.add(valueDeser.deserialize(jp, ctxt)); } return result; } } </code></pre> <p>Is there a better/simpler way to do this?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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