DATAREST-328, DATAREST-320 - AssociationOmittingSerializerModifier now correctly considers renamed properties.

Previously, if a persistent property was renamed using e.g. @JsonProperty, the lookup of the PersistentProperty failed as BeanPropertyWriter exposes the final (renamed) property name, not the internal one. We now defensively lookup the correct BeanPropertyDescriptor using the external name and use the corresponding internal one for the PersistentProperty lookup.
This commit is contained in:
Oliver Gierke
2014-06-27 18:42:48 +02:00
parent ed77540a81
commit 2bfa422ee7
2 changed files with 94 additions and 3 deletions

View File

@@ -61,6 +61,7 @@ import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
import com.fasterxml.jackson.databind.deser.ValueInstantiator;
import com.fasterxml.jackson.databind.deser.std.CollectionDeserializer;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerBuilder;
@@ -186,7 +187,7 @@ public class PersistentEntityJackson2Module extends SimpleModule {
*
* @author Oliver Gierke
*/
private static class AssociationOmittingSerializerModifier extends BeanSerializerModifier {
static class AssociationOmittingSerializerModifier extends BeanSerializerModifier {
private final PersistentEntities entities;
private final RepositoryRestConfiguration configuration;
@@ -200,7 +201,7 @@ public class PersistentEntityJackson2Module extends SimpleModule {
* @param associationLinks must not be {@literal null}.
* @param configuration must not be {@literal null}.
*/
private AssociationOmittingSerializerModifier(PersistentEntities entities, AssociationLinks associationLinks,
public AssociationOmittingSerializerModifier(PersistentEntities entities, AssociationLinks associationLinks,
RepositoryRestConfiguration configuration) {
Assert.notNull(entities, "PersistentEntities must not be null!");
@@ -231,7 +232,7 @@ public class PersistentEntityJackson2Module extends SimpleModule {
for (BeanPropertyWriter writer : builder.getProperties()) {
// Skip exported associations
PersistentProperty<?> persistentProperty = entity.getPersistentProperty(writer.getName());
PersistentProperty<?> persistentProperty = findProperty(writer.getName(), entity, beanDesc);
if (persistentProperty == null) {
continue;
@@ -253,6 +254,27 @@ public class PersistentEntityJackson2Module extends SimpleModule {
return builder;
}
/**
* Returns the {@link PersistentProperty} for the property with the given final name (the name that it will be
* rendered under eventually).
*
* @param finalName the output name the property will be rendered under.
* @param entity the {@link PersistentEntity} to find the property on.
* @param description the Jackson {@link BeanDescription}.
* @return
*/
private PersistentProperty<?> findProperty(String finalName, PersistentEntity<?, ?> entity,
BeanDescription description) {
for (BeanPropertyDefinition definition : description.findProperties()) {
if (definition.getName().equals(finalName)) {
return entity.getPersistentProperty(definition.getInternalName());
}
}
return null;
}
}
/**

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2014 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.rest.webmvc.json;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.mapping.context.PersistentEntities;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.mapping.AssociationLinks;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
/**
* Unit tests for {@link PersistentEntityJackson2Module}.
*
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
public class PersistentEntityJackson2ModuleUnitTests {
@Mock AssociationLinks associationLinks;
/**
* @see DATAREST-328, DATAREST-320
*/
@Test
public void doesNotDropPropertiesWithCustomizedNames() throws Exception {
MongoMappingContext mappingContext = new MongoMappingContext();
mappingContext.getPersistentEntity(Sample.class);
PersistentEntities persistentEntities = new PersistentEntities(Arrays.asList(mappingContext));
SimpleModule module = new SimpleModule();
module.setSerializerModifier(new PersistentEntityJackson2Module.AssociationOmittingSerializerModifier(
persistentEntities, associationLinks, new RepositoryRestConfiguration()));
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
assertThat(mapper.writeValueAsString(new Sample()), is(notNullValue()));
}
static class Sample {
public @JsonProperty("foo") String name;
}
}