From b5ce20a0fb28575ee20114de33e3c5157aed855d Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Mon, 18 Jan 2021 16:44:27 +0100 Subject: [PATCH] #1435 - 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 9c422b9f..f4cf4f23 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; @@ -213,7 +215,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 4133700c..38236daa 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; + } }