From 894de4a245154375210c388489cf93b69b913ef7 Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Mon, 18 Jan 2021 16:44:27 +0100 Subject: [PATCH] #1434 - EntityModel now explicitly rejects types rendered as @JsonValue. It doesn't make sense to wrap an object to be rendered as value into an EntityModel as the latter will end up as JSON Object and thus, the representation of the target object *needs* to consist of key-value pairs. Previously we just produced invalid JSON which ultimately failed as well. --- .../springframework/hateoas/EntityModel.java | 11 +++++++++- .../hateoas/EntityModelUnitTest.java | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/hateoas/EntityModel.java b/src/main/java/org/springframework/hateoas/EntityModel.java index ddc6fd6a..8724d710 100644 --- a/src/main/java/org/springframework/hateoas/EntityModel.java +++ b/src/main/java/org/springframework/hateoas/EntityModel.java @@ -29,8 +29,10 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.JsonValueSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.util.NameTransformer; @@ -212,7 +214,14 @@ public class EntityModel extends RepresentationModel> { return; } - provider.findValueSerializer(value.getClass()) // + JsonSerializer serializer = provider.findValueSerializer(value.getClass()); + + if (JsonValueSerializer.class.isInstance(serializer)) { + throw new IllegalStateException( + "@JsonValue rendered classes can not be directly nested in EntityModel as they do not produce a document key!"); + } + + serializer // .unwrappingSerializer(NameTransformer.NOP) // .serialize(value, gen, provider); } diff --git a/src/test/java/org/springframework/hateoas/EntityModelUnitTest.java b/src/test/java/org/springframework/hateoas/EntityModelUnitTest.java index 991a50fe..ee04c63f 100755 --- a/src/test/java/org/springframework/hateoas/EntityModelUnitTest.java +++ b/src/test/java/org/springframework/hateoas/EntityModelUnitTest.java @@ -21,6 +21,10 @@ import java.util.Collections; import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.annotation.JsonValue; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + /** * Unit tests for {@link EntityModel}. * @@ -73,4 +77,20 @@ class EntityModelUnitTest { EntityModel.of(Collections.emptyList()); }); } + + @Test // #1371 + void producesProperExceptionWhenRenderingAJsonValue() throws Exception { + + EntityModel model = EntityModel.of(new ValueType()); + + assertThatExceptionOfType(JsonMappingException.class) + .isThrownBy(() -> new ObjectMapper().writeValueAsString(model)) + .withMessageContaining("@JsonValue"); + } + + // #1371 + + static class ValueType { + @JsonValue String type; + } }