From 8df3dfcd7a79991066b1a5dc5d6cd4db70016a0b Mon Sep 17 00:00:00 2001 From: Yih Tsern Date: Wed, 3 May 2023 17:57:11 +0800 Subject: [PATCH] Record constructor with single write-only parameter should result in properties-based creator, to fix #3897. --- .../deser/BasicDeserializerFactory.java | 4 ++ .../databind/records/RecordBasicsTest.java | 61 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java index adbfcdc012..da4c3bddfb 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java @@ -1032,6 +1032,10 @@ private boolean _checkIfCreatorPropertyBased(BeanDescription beanDesc, } } } + // [databind#3897]: Record canonical constructor will have implicitly named propDef + if (propDef != null && !propDef.isExplicitlyNamed() && beanDesc.isRecordType()) { + return true; + } // in absence of everything else, default to delegating return false; } diff --git a/src/test-jdk14/java/com/fasterxml/jackson/databind/records/RecordBasicsTest.java b/src/test-jdk14/java/com/fasterxml/jackson/databind/records/RecordBasicsTest.java index f94231b526..c2dfb3261d 100644 --- a/src/test-jdk14/java/com/fasterxml/jackson/databind/records/RecordBasicsTest.java +++ b/src/test-jdk14/java/com/fasterxml/jackson/databind/records/RecordBasicsTest.java @@ -40,6 +40,20 @@ record SnakeRecord(String myId, String myValue){} record RecordWithJsonDeserialize(int id, @JsonDeserialize(converter = StringTrimmer.class) String name) { } + record RecordSingleWriteOnly(@JsonProperty(access = JsonProperty.Access.WRITE_ONLY) int id) { } + + record RecordSomeWriteOnly( + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) int id, + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) String name, + String email) { + } + + record RecordAllWriteOnly( + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) int id, + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) String name, + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) String email) { + } + private final ObjectMapper MAPPER = newJsonMapper(); /* @@ -204,6 +218,53 @@ public void testDeserializeJsonDeserializeRecord() throws Exception { assertEquals(new RecordWithJsonDeserialize(123, "Bob"), value); } + /* + /********************************************************************** + /* Test methods, JsonProperty(access=WRITE_ONLY) + /********************************************************************** + */ + + public void testSerialize_SingleWriteOnlyParameter() throws Exception { + String json = MAPPER.writeValueAsString(new RecordSingleWriteOnly(123)); + + assertEquals("{}", json); + } + + // [databind#3897] + public void testDeserialize_SingleWriteOnlyParameter() throws Exception { + RecordSingleWriteOnly value = MAPPER.readValue("{\"id\":123}", RecordSingleWriteOnly.class); + + assertEquals(new RecordSingleWriteOnly(123), value); + } + + public void testSerialize_SomeWriteOnlyParameter() throws Exception { + String json = MAPPER.writeValueAsString(new RecordSomeWriteOnly(123, "Bob", "bob@example.com")); + + assertEquals("{\"email\":\"bob@example.com\"}", json); + } + + public void testDeserialize_SomeWriteOnlyParameter() throws Exception { + RecordSomeWriteOnly value = MAPPER.readValue( + "{\"id\":123,\"name\":\"Bob\",\"email\":\"bob@example.com\"}", + RecordSomeWriteOnly.class); + + assertEquals(new RecordSomeWriteOnly(123, "Bob", "bob@example.com"), value); + } + + public void testSerialize_AllWriteOnlyParameter() throws Exception { + String json = MAPPER.writeValueAsString(new RecordAllWriteOnly(123, "Bob", "bob@example.com")); + + assertEquals("{}", json); + } + + public void testDeserialize_AllWriteOnlyParameter() throws Exception { + RecordAllWriteOnly value = MAPPER.readValue( + "{\"id\":123,\"name\":\"Bob\",\"email\":\"bob@example.com\"}", + RecordAllWriteOnly.class); + + assertEquals(new RecordAllWriteOnly(123, "Bob", "bob@example.com"), value); + } + /* /********************************************************************** /* Internal helper methods