How to skip wrapper object in jackson json deserialization
You can create a custom annotation with @JsonDeserialize
inside and create a custom JsonDeserializer
that implements ContextualDeserializer
. The idea is inspired from the solution you mentioned but it is more general to unwrap any one property in a json object.
Following is the custom annotation using @JacksonAnnotationsInside
as annotation container contains @JsonDeserialize
:
@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotationsInside@JsonDeserialize(using = JsonUnwrapPropertyDeserializer.class)public @interface JsonUnwrapProperty {}
and the custom JsonDeserializer
that implements ContextualDeserializer
:
public class JsonUnwrapPropertyDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer { private JavaType unwrappedJavaType; private String unwrappedProperty; @Override public JsonDeserializer<?> createContextual(final DeserializationContext deserializationContext, final BeanProperty beanProperty) throws JsonMappingException { unwrappedProperty = beanProperty.getMember().getName(); unwrappedJavaType = beanProperty.getType(); return this; } @Override public Object deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException { final TreeNode targetObjectNode = jsonParser.readValueAsTree().get(unwrappedProperty); return jsonParser.getCodec().readValue(targetObjectNode.traverse(), unwrappedJavaType); }}
and the usage example:
public class MyBean { @JsonProperty("broadcastPresenceRoles") @JsonUnwrapProperty private List<String> broadcastPresenceRole; @JsonProperty("admins") @JsonUnwrapProperty private String admin; // constructor, getter and setter}
@JsonProperty
is to locate the wrapper object and @JsonUnwrappProperty
is to deserialize the json object and extract a property into the annotated field.
Edited:
Following is an example with ObjectMapper
:
String json = "{\n" + " \"broadcastPresenceRoles\": {\n" + " \"broadcastPresenceRole\": [\n" + " \"moderator\",\n" + " \"participant\",\n" + " \"visitor\"\n" + " ]\n" + " },\n" + " \"admins\": {\n" + " \"admin\": \"sanjeet@shahanshah\"\n" + " }\n" + "}";final ObjectMapper mapper = new ObjectMapper();final MyBean myBean = mapper.readValue(json, MyBean.class);System.out.println(myBean.getBroadcastPresenceRole());System.out.println(myBean.getAdmin());
Output:
[moderator, participant, visitor]
sanjeet@shahanshah
I created a variation that solved the NPE based on @wilson response
import java.io.IOException;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;import com.fasterxml.jackson.core.JsonParser;import com.fasterxml.jackson.core.JsonToken;import com.fasterxml.jackson.databind.BeanProperty;import com.fasterxml.jackson.databind.DeserializationContext;import com.fasterxml.jackson.databind.JavaType;import com.fasterxml.jackson.databind.JsonDeserializer;import com.fasterxml.jackson.databind.JsonMappingException;import com.fasterxml.jackson.databind.annotation.JsonDeserialize;import com.fasterxml.jackson.databind.deser.ContextualDeserializer;@Retention(RetentionPolicy.RUNTIME)@JacksonAnnotationsInside@JsonDeserialize(using = JsonUnwrapProperty.JsonUnwrapPropertyDeserializer.class)public @interface JsonUnwrapProperty { public static class JsonUnwrapPropertyDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer { private JavaType unwrappedJavaType; private String unwrappedProperty; @Override public JsonDeserializer<?> createContextual(final DeserializationContext deserializationContext, final BeanProperty beanProperty) throws JsonMappingException { unwrappedProperty = beanProperty.getMember().getName(); unwrappedJavaType = beanProperty.getType(); return this; } @Override public Object deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException { System.out.println(String.format("Ignoring %s in %s/%s", unwrappedProperty, jsonParser.currentName(), jsonParser.nextFieldName())); JsonToken token = jsonParser.nextValue(); return jsonParser.getCodec().readValue(jsonParser, unwrappedJavaType); } }}