#1354 - Render Map entries once.

Maps, when wrapped inside an EntityModel, were getting double-rendered. Fix it so that they are only rendered once.

Original pull request: #1353.
This commit is contained in:
Greg L. Turnquist
2020-08-11 13:57:42 -05:00
committed by Oliver Drotbohm
parent f4f122e7bd
commit 657406034f
3 changed files with 27 additions and 5 deletions

View File

@@ -21,6 +21,8 @@ import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -118,7 +120,7 @@ public class EntityModel<T> extends RepresentationModel<EntityModel<T>> {
@JsonUnwrapped
@Nullable
public T getContent() {
return content;
return !Map.class.isInstance(content) ? content : null;
}
// Hacks to allow deserialization into an EntityModel<Map<String, Object>>
@@ -126,7 +128,7 @@ public class EntityModel<T> extends RepresentationModel<EntityModel<T>> {
@Nullable
@JsonAnyGetter
@SuppressWarnings("unchecked")
private Map<String, Object> getMapContent() {
public Map<String, Object> getMapContent() {
return Map.class.isInstance(content) ? (Map<String, Object>) content : null;
}

View File

@@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
@@ -591,7 +592,8 @@ class Jackson2HalIntegrationTest {
EntityModel<Map<String, Object>> result = mapper.readValue(source, modelType);
assertThat(result.getContent()).containsEntry("key", "value");
assertThat(result.getContent()).isNull();
assertThat(result.getMapContent()).containsEntry("key", "value");
}
@Test // #1157
@@ -606,6 +608,22 @@ class Jackson2HalIntegrationTest {
assertThat(result.getContent().name).isEqualTo("Dave");
}
@Test // #1352
void rendersMapWithoutDuplicateEntries() throws JsonProcessingException {
Map<String, String> map = new TreeMap<>();
map.put("key", "value");
map.put("key2", "value2");
EntityModel<Map<String, String>> entityModel = EntityModel.of(map);
entityModel.add(Link.of("http://example.com"));
String serialized = mapper.writeValueAsString(entityModel);
assertThat(serialized)
.isEqualTo("{\"_links\":{\"self\":{\"href\":\"http://example.com\"}},\"key\":\"value\",\"key2\":\"value2\"}");
}
@Relation(collectionRelation = "someSample")
static class SomeSample {
@JsonProperty String name;

View File

@@ -64,8 +64,10 @@ class ReactiveRepresentationModelAssemblerBuilderDslUnitTest : TestUtils() {
runBlocking {
val collectionModel = testResourceAssembler.toCollectionModelAndAwait(employees, exchange)
assertThat(collectionModel.content.flatMap { entityModel -> entityModel.links })
.containsExactlyInAnyOrder(Link.of("/employees", EMPLOYEES_RELATION), Link.of("/employees", EMPLOYEES_RELATION))
val extractLinks: (EntityModel<Employee>) -> Iterable<Link> = { entityModel -> entityModel.links }
assertThat(collectionModel.content.flatMap(extractLinks))
.containsExactlyInAnyOrder(Link.of("/employees", EMPLOYEES_RELATION), Link.of("/employees", EMPLOYEES_RELATION))
}
}