diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java index d58c684775..52921f1bd0 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java @@ -5,9 +5,9 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.databind.deser.SettableAnyProperty; -import com.fasterxml.jackson.databind.deser.SettableBeanProperty; +import com.fasterxml.jackson.databind.deser.*; import com.fasterxml.jackson.databind.introspect.AnnotatedMember; +import com.fasterxml.jackson.databind.util.ClassUtil; /** * Simple container used for temporarily buffering a set of @@ -335,7 +335,12 @@ public Object handleIdValue(final DeserializationContext ctxt, Object bean) thro // also: may need to set a property value as well SettableBeanProperty idProp = _objectIdReader.idProperty; if (idProp != null) { - return idProp.setAndReturn(bean, _idValue); + // [databind#5328] Records/Creators do not have setters, skip + if (idProp instanceof CreatorProperty) { + return bean; + } else { + return idProp.setAndReturn(bean, _idValue); + } } } else { // 07-Jun-2016, tatu: Trying to improve error messaging here... diff --git a/src/test-jdk17/java/com/fasterxml/jackson/databind/records/JsonIdentityOnRecord5238Test.java b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/JsonIdentityOnRecord5238Test.java new file mode 100644 index 0000000000..7cc68774a9 --- /dev/null +++ b/src/test-jdk17/java/com/fasterxml/jackson/databind/records/JsonIdentityOnRecord5238Test.java @@ -0,0 +1,83 @@ +package com.fasterxml.jackson.databind.records; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.annotation.*; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.testutil.DatabindTestUtil; + +import static org.junit.jupiter.api.Assertions.*; + +// [databind#5238] immutable classes with @JsonIdentityInfo can be deserialized; records cannot +public class JsonIdentityOnRecord5238Test + extends DatabindTestUtil +{ + // Record-based data + record ExampleRecord(List allThings, ThingRecord selected) { } + + @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") + record ThingRecord(int id, String name) { } + + // POJO-based data + static class ExamplePojo { + public List allThings; + public ThingPojo selected; + + @JsonCreator + public ExamplePojo( + @JsonProperty("allThings") List allThings, + @JsonProperty("selected") ThingPojo selected) { + this.allThings = allThings; + this.selected = selected; + } + } + + @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") + static class ThingPojo { + public final int id; + public final String name; + + @JsonCreator + public ThingPojo(@JsonProperty("prefixId") int id, @JsonProperty("name") String name) { + this.id = id; + this.name = name; + } + } + + private final ObjectMapper MAPPER = newJsonMapper(); + + @Test + void testIdentityWithPojo() throws Exception { + ThingPojo t1 = new ThingPojo(1, "a"); + ThingPojo t2 = new ThingPojo(2, "b"); + ExamplePojo input = new ExamplePojo(List.of(t1, t2), t2); + + String json = MAPPER.writeValueAsString(input); + + // Then : Check deserialization result, values + ExamplePojo result = MAPPER.readValue(json, ExamplePojo.class); + assertEquals(input.allThings.size(), result.allThings.size()); + assertEquals(input.selected.id, result.selected.id); + assertEquals(input.selected.name, result.selected.name); + } + + @Test + void testIdentityWithRecord() throws Exception { + // Given + ThingRecord t1 = new ThingRecord(1, "a"); + ThingRecord t2 = new ThingRecord(2, "b"); + ExampleRecord input = new ExampleRecord(List.of(t1, t2), t2); + + // When + String json = MAPPER.writeValueAsString(input); + ExampleRecord result = MAPPER.readValue(json, ExampleRecord.class); + + // Then + assertEquals(input.allThings.size(), result.allThings.size()); + assertEquals(input.selected.id, result.selected.id); + assertEquals(input.selected.name, result.selected.name); + } + +} \ No newline at end of file