From b65e0c911806f1ac5b7e507713e22abe40febddc Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Tue, 21 Feb 2023 13:24:39 +0100 Subject: [PATCH] Adapt to renamed properties by using MappedProperties in association deserialization. Revert the changes that employed manual annotation lookup as that would cause invalid associations of fields and accessor methods for properties shadow renamed. Instead, we now use MappedProperties that already contains a mapping between the Jackson field names and Sprign Data property names. Fixes: #2165 --- .../rest/webmvc/json/MappedProperties.java | 4 ++++ .../json/PersistentEntityJackson2Module.java | 18 +++--------------- ...ersistentEntityJackson2ModuleUnitTests.java | 9 +-------- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java index bb14a0853..0517577c1 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/MappedProperties.java @@ -151,6 +151,10 @@ class MappedProperties { return new MappedProperties(entity, description); } + public static MappedProperties forDescription(PersistentEntity entity, BeanDescription description) { + return new MappedProperties(entity, description); + } + public static MappedProperties none() { return new MappedProperties(Collections.emptyMap(), Collections.emptyMap(), Collections.emptySet(), Collections.emptySet(), false); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java index d7a502160..6a72a1355 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java @@ -24,7 +24,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Objects; import java.util.Optional; import org.slf4j.Logger; @@ -83,8 +82,6 @@ import com.fasterxml.jackson.databind.deser.std.CollectionDeserializer; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator; -import com.fasterxml.jackson.databind.introspect.AnnotatedField; -import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.fasterxml.jackson.databind.module.SimpleModule; @@ -445,21 +442,12 @@ public class PersistentEntityJackson2Module extends SimpleModule { entities.getPersistentEntity(beanDesc.getBeanClass()).ifPresent(entity -> { + MappedProperties mapped = MappedProperties.forDescription(entity, beanDesc); + while (properties.hasNext()) { SettableBeanProperty property = properties.next(); - // To find the PersistentProperty name in case there is a @JsonProperty annotation - // on the field. Both BeanPropertyDefinition#getName() and BeanPropertyDefinition#getInternalName() - // don't return the actual name of the field, so we look up the AnnotatedField itself to retrieve - // the real name from, so it can be used for PersistentProperty lookup - String persistentPropertyName = beanDesc.findProperties().stream() - .filter(propertyDefinition -> property.getName().equals(propertyDefinition.getName())) - .map(BeanPropertyDefinition::getField).filter(Objects::nonNull).map(AnnotatedField::getName).findFirst() - // Fall back to the JSON name in case we can't find a BeanPropertyDefinition, - // so things can be mapped by convention in case they are immutable objects and are - // using constructor injection - .orElse(property.getName()); - PersistentProperty persistentProperty = entity.getPersistentProperty(persistentPropertyName); + PersistentProperty persistentProperty = mapped.getPersistentProperty(property.getName()); if (persistentProperty == null) { continue; diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java index 3bf1630dd..7028068cd 100755 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2ModuleUnitTests.java @@ -19,7 +19,6 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -import lombok.AccessLevel; import lombok.Data; import lombok.Getter; @@ -190,10 +189,9 @@ class PersistentEntityJackson2ModuleUnitTests { PetOwner petOwner = mapper.readValue("{\"package\":\"/packages/1\"}", PetOwner.class); assertThat(petOwner).isNotNull(); - assertThat(petOwner.getPackage()).isNotNull(); + assertThat(petOwner._package).isNotNull(); } - @Test // DATAREST-1321 void allowsNumericIdsForLookupTypes() throws Exception { @@ -298,12 +296,7 @@ class PersistentEntityJackson2ModuleUnitTests { Pet pet; Home home; - @Getter(value = AccessLevel.NONE) @JsonProperty("package") Package _package; - - public Package getPackage() { - return _package; - } } static class Package {}