DATAREST-654 - Additional tweaks and tests for enum deserialization.

Made the EnumTranslatingDeserializer contextual to make sure we get access to the BeanProperty and thus the actual enum target type.
This commit is contained in:
Oliver Gierke
2015-08-21 17:03:27 +02:00
parent 9280a4e4b6
commit 8ed188cbc2
2 changed files with 64 additions and 4 deletions

View File

@@ -27,8 +27,12 @@ import org.springframework.util.Assert;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
@@ -122,11 +126,12 @@ public class JacksonSerializers extends SimpleModule {
* @author Oliver Gierke
*/
@SuppressWarnings("rawtypes")
public static class EnumTranslatingDeserializer extends StdDeserializer<Enum> {
public static class EnumTranslatingDeserializer extends StdDeserializer<Enum>implements ContextualDeserializer {
private static final long serialVersionUID = 5305284644923180079L;
private final EnumTranslator translator;
private final BeanProperty property;
/**
* Creates a new {@link EnumTranslatingDeserializer} using the given {@link EnumTranslator}.
@@ -134,11 +139,34 @@ public class JacksonSerializers extends SimpleModule {
* @param translator must not be {@literal null}.
*/
public EnumTranslatingDeserializer(EnumTranslator translator) {
this(translator, null);
}
/**
* Creates a new {@link EnumTranslatingDeserializer} using the given {@link EnumTranslator} and {@link BeanProperty}
* .
*
* @param translator must not be {@literal null}.
* @param property can be {@literal null}.
*/
public EnumTranslatingDeserializer(EnumTranslator translator, BeanProperty property) {
super(Enum.class);
Assert.notNull(translator, "EnumTranslator must not be null!");
this.translator = translator;
this.property = property;
}
/*
* (non-Javadoc)
* @see com.fasterxml.jackson.databind.deser.ContextualDeserializer#createContextual(com.fasterxml.jackson.databind.DeserializationContext, com.fasterxml.jackson.databind.BeanProperty)
*/
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property)
throws JsonMappingException {
return new EnumTranslatingDeserializer(translator, property);
}
/*
@@ -148,7 +176,12 @@ public class JacksonSerializers extends SimpleModule {
@Override
@SuppressWarnings("unchecked")
public Enum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return translator.fromText((Class<? extends Enum<?>>) ctxt.getContextualType().getRawClass(), p.getText());
if (property == null) {
throw new IllegalStateException("Can only translate enum with property information!");
}
return translator.fromText((Class<? extends Enum<?>>) property.getType().getRawClass(), p.getText());
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,6 +27,10 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.context.support.StaticMessageSource;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
@@ -40,6 +44,7 @@ import org.springframework.data.rest.webmvc.jpa.PersonRepository;
import org.springframework.data.rest.webmvc.jpa.UserExcerpt;
import org.springframework.data.rest.webmvc.mongodb.Address;
import org.springframework.data.rest.webmvc.mongodb.User;
import org.springframework.data.rest.webmvc.mongodb.User.Gender;
import org.springframework.data.rest.webmvc.util.TestUtils;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.LinkDiscoverer;
@@ -67,7 +72,7 @@ import com.jayway.jsonpath.JsonPath;
* @author Oliver Gierke
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = RepositoryTestsConfig.class)
@ContextConfiguration(classes = { RepositoryTestsConfig.class, PersistentEntitySerializationTests.TestConfig.class })
@Transactional
public class PersistentEntitySerializationTests {
@@ -78,6 +83,20 @@ public class PersistentEntitySerializationTests {
@Autowired PersonRepository people;
@Autowired OrderRepository orders;
@Configuration
static class TestConfig extends RepositoryTestsConfig {
@Bean
@Override
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = super.objectMapper();
objectMapper.registerModule(
new JacksonSerializers(new EnumTranslator(new MessageSourceAccessor(new StaticMessageSource()))));
return objectMapper;
}
}
LinkDiscoverer linkDiscoverer;
ProjectionFactory projectionFactory;
@@ -277,4 +296,12 @@ public class PersistentEntitySerializationTests {
assertThat(JsonPath.read(result, "$_links.processed"), is(notNullValue()));
}
/**
* @see DATAREST-654
*/
@Test
public void deserializesTranslatedEnumProperty() throws Exception {
assertThat(mapper.readValue("{ \"gender\" : \"Male\" }", User.class).gender, is(Gender.MALE));
}
}