Skip to content

Commit 035fba3

Browse files
authored
Fix #3992: avoid too early/eager removal of accessors (#4053)
1 parent daa0361 commit 035fba3

File tree

4 files changed

+64
-8
lines changed

4 files changed

+64
-8
lines changed

release-notes/VERSION-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ Project: jackson-databind
2727
(contributed by Joo-Hyuk K)
2828
#3965: Add `JsonNodeFeature.WRITE_PROPERTIES_SORTED` for sorting `ObjectNode` properties
2929
on serialization
30+
#3992: `@JsonIgnore` on Record property ignored if there is getter override
31+
(reported by @ennishol)
3032
#4008: Optimize `ObjectNode` findValue(s) and findParent(s) fast paths
3133
(contributed by David S)
3234
#4009: Locale "" is deserialised as `null` if `ACCEPT_EMPTY_STRING_AS_NULL_OBJECT`

src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java

+9-6
Original file line numberDiff line numberDiff line change
@@ -976,12 +976,15 @@ protected void _removeUnwantedProperties(Map<String, POJOPropertyBuilder> props)
976976
// Otherwise, check ignorals
977977
if (prop.anyIgnorals()) {
978978
// Special handling for Records, as they do not have mutators so relying on constructors
979-
// with (mostly) implicitly-named parameters...
980-
if (isRecordType()) {
981-
// ...so can only remove ignored field and/or accessors, not constructor parameters that are needed
982-
// for instantiation...
983-
prop.removeIgnored();
984-
// ...which will then be ignored (the incoming property value) during deserialization
979+
// with (mostly) implicitly-named parameters...
980+
// 20-Jul-2023, tatu: This can be harmful, see f.ex [databind#3992] so
981+
// only use special handling for deserialization
982+
983+
if (isRecordType() && !_forSerialization) {
984+
// ...so can only remove ignored field and/or accessors, not constructor parameters that are needed
985+
// for instantiation...
986+
prop.removeIgnored();
987+
// ...which will then be ignored (the incoming property value) during deserialization
985988
_collectIgnorals(prop.getName());
986989
continue;
987990
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.fasterxml.jackson.databind.records;
2+
3+
import java.util.*;
4+
5+
import com.fasterxml.jackson.annotation.JsonIgnore;
6+
import com.fasterxml.jackson.databind.BaseMapTest;
7+
import com.fasterxml.jackson.databind.ObjectMapper;
8+
9+
public class RecordWithIgnoreOverride3992Test extends BaseMapTest
10+
{
11+
// [databind#3992]
12+
public record HelloRecord(String text, @JsonIgnore Recursion hidden) {
13+
// Before fix: works if this override is removed
14+
// After fix: works either way
15+
@Override
16+
public Recursion hidden() {
17+
return hidden;
18+
}
19+
}
20+
21+
static class Recursion {
22+
public List<Recursion> all = new ArrayList<>();
23+
24+
void add(Recursion recursion) {
25+
all.add(recursion);
26+
}
27+
}
28+
29+
private final ObjectMapper MAPPER = newJsonMapper();
30+
31+
/*
32+
/**********************************************************************
33+
/* Test methods
34+
/**********************************************************************
35+
*/
36+
37+
// [databind#3992]
38+
public void testHelloRecord() throws Exception {
39+
Recursion beanWithRecursion = new Recursion();
40+
beanWithRecursion.add(beanWithRecursion);
41+
String json = MAPPER.writer()
42+
.writeValueAsString(new HelloRecord("hello", beanWithRecursion));
43+
assertEquals(a2q("{'text':'hello'}"), json);
44+
45+
// Let's check deserialization works too, just in case.
46+
HelloRecord result = MAPPER.readValue(json, HelloRecord.class);
47+
assertNotNull(result);
48+
}
49+
}

src/test-jdk14/java/com/fasterxml/jackson/databind/records/RecordWithJsonIgnoreTest.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public void testSerializeJsonIgnoreRecord() throws Exception {
3939
}
4040

4141
public void testDeserializeJsonIgnoreRecord() throws Exception {
42-
RecordWithIgnore value = MAPPER.readValue("{\"id\":123,\"name\":\"Bob\"}", RecordWithIgnore.class);
42+
RecordWithIgnore value = MAPPER.readValue("{\"id\":123,\"name\":\"Bob\"}",
43+
RecordWithIgnore.class);
4344
assertEquals(new RecordWithIgnore(123, null), value);
4445
}
4546

@@ -71,7 +72,8 @@ public void testSerializeJsonIgnoreAccessorRecord() throws Exception {
7172
}
7273

7374
public void testDeserializeJsonIgnoreAccessorRecord() throws Exception {
74-
RecordWithIgnoreAccessor value = MAPPER.readValue("{\"id\":123,\"name\":\"Bob\"}", RecordWithIgnoreAccessor.class);
75+
RecordWithIgnoreAccessor value = MAPPER.readValue("{\"id\":123,\"name\":\"Bob\"}",
76+
RecordWithIgnoreAccessor.class);
7577
assertEquals(new RecordWithIgnoreAccessor(123, null), value);
7678
}
7779

0 commit comments

Comments
 (0)