From 95d62fb18c3fe1209ffaffe8a2d6ee1b4c719559 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Thu, 15 Sep 2016 16:33:59 +0200 Subject: [PATCH] DATAREST-864 - NestedEntitySerializer now handles Maps correctly. Previously, NestedEntitySerializer failed to handle Maps correctly as the logic to convert the found values to nested resources tried to handle the values as is, not explicitly looking at the values instead. We now use an explicit code path to turn the values into resources so that links pointing to other resources are rendered correctly. Original pull request: #219. --- .../data/rest/tests/mongodb/User.java | 11 ++++++++++ .../PersistentEntitySerializationTests.java | 21 +++++++++++++++++++ .../json/PersistentEntityJackson2Module.java | 13 ++++++++++++ 3 files changed, 45 insertions(+) diff --git a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/User.java b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/User.java index 0a8304484..73d46ff09 100644 --- a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/User.java +++ b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/main/java/org/springframework/data/rest/tests/mongodb/User.java @@ -15,9 +15,13 @@ */ package org.springframework.data.rest.tests.mongodb; +import lombok.Value; + import java.math.BigInteger; import java.time.LocalDateTime; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; import org.springframework.data.annotation.ReadOnlyProperty; @@ -47,6 +51,7 @@ public class User { public org.joda.time.LocalDateTime jodaDateTime; public TypeWithPattern pattern; public @DBRef(lazy = true) List colleagues; + public Map colleaguesMap = new HashMap(); public static class EmailAddress { @@ -67,4 +72,10 @@ public class User { } public static class TypeWithPattern {} + + @Value + public static class Nested { + public @DBRef(lazy = true) User user; + public String foo = "foo"; + } } diff --git a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java index 0857b5b95..622408978 100644 --- a/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java +++ b/spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java @@ -19,6 +19,7 @@ import static org.hamcrest.MatcherAssert.*; import static org.hamcrest.Matchers.*; import java.util.Arrays; +import java.util.HashMap; import org.junit.Before; import org.junit.Test; @@ -36,6 +37,8 @@ import org.springframework.data.rest.tests.mongodb.Address; import org.springframework.data.rest.tests.mongodb.MongoDbRepositoryConfig; import org.springframework.data.rest.tests.mongodb.User; import org.springframework.data.rest.tests.mongodb.User.Gender; +import org.springframework.data.rest.tests.mongodb.User.Nested; +import org.springframework.data.rest.tests.mongodb.UserRepository; import org.springframework.data.rest.webmvc.PersistentEntityResource; import org.springframework.hateoas.Link; import org.springframework.hateoas.LinkDiscoverer; @@ -65,6 +68,7 @@ public class PersistentEntitySerializationTests { @Autowired ObjectMapper mapper; @Autowired Repositories repositories; + @Autowired UserRepository users; @Configuration static class TestConfig extends RepositoryTestsConfig { @@ -122,4 +126,21 @@ public class PersistentEntitySerializationTests { public void deserializesTranslatedEnumProperty() throws Exception { assertThat(mapper.readValue("{ \"gender\" : \"Male\" }", User.class).gender, is(Gender.MALE)); } + + /** + * @see DATAREST-864 + */ + @Test + public void createsNestedResourceForMap() throws Exception { + + User dave = users.save(new User()); + dave.colleaguesMap = new HashMap(); + dave.colleaguesMap.put("carter", new Nested(users.save(new User()))); + + PersistentEntityResource resource = PersistentEntityResource + .build(dave, repositories.getPersistentEntity(User.class)).build(); + + assertThat(JsonPath.parse(mapper.writeValueAsString(resource)).read("$.colleaguesMap.carter._links.user.href", + String.class), is(notNullValue())); + } } 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 6de7b0149..9ce1f9bb2 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,6 +24,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -352,6 +354,17 @@ public class PersistentEntityJackson2Module extends SimpleModule { provider.defaultSerializeValue(resources, gen); + } else if (value instanceof Map) { + + Map source = (Map) value; + Map resources = CollectionFactory.createMap(value.getClass(), source.size()); + + for (Entry entry : source.entrySet()) { + resources.put(entry.getKey(), toResource(entry.getValue())); + } + + provider.defaultSerializeValue(resources, gen); + } else { provider.defaultSerializeValue(toResource(value), gen); }