Skip to content

Instantly share code, notes, and snippets.

@sverhagen
Created August 6, 2017 06:23
Show Gist options
  • Save sverhagen/c199d924245a078c287b46546e1ac26c to your computer and use it in GitHub Desktop.
Save sverhagen/c199d924245a078c287b46546e1ac26c to your computer and use it in GitHub Desktop.
Contextual deserializer for generic wrapper type in Jackson
package com.example;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
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.ObjectMapper;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* Since {@link PagedResult} and friends are created via {@link PagedResultCreator}, and have always had non-default
* constructors, it is hard to deserialize them within unit tests using Jackson. This deserializer determines requested
* type (it implements {@link ContextualDeserializer} so that it gets this information from Jackson, based ultimately on
* whatever we pass into e.g. {@code RestAssured... .andReturn().as(ThisType.class)}. It then creates its own
* implementation of {@link PagedResult}, i.e. {@link PagedResultImplForTest}.
*/
public class PagedResultDeserializer extends JsonDeserializer<PagedResult<?>>
implements ContextualDeserializer {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private JavaType valueType;
public PagedResultDeserializer(JavaType valueType) {
this.valueType = valueType;
}
public PagedResultDeserializer() {
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property)
throws JsonMappingException {
JavaType pagedResultType = property.getType();
JavaType valueType = pagedResultType.containedType(0);
return new PagedResultDeserializer(valueType);
}
@Override
public PagedResult<?> deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
TypeFactory typeFactory = ctxt.getTypeFactory();
CollectionType itemsListType = typeFactory.constructCollectionType(List.class, valueType);
ObjectCodec objectCodec = jsonParser.getCodec();
Map properties = objectCodec.readValue(jsonParser, Map.class);
Object items = properties.remove("items");
List<?> itemsList = OBJECT_MAPPER.convertValue(items, itemsListType);
return new PagedResultImplForTest<>(properties, itemsList);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment