Skip to content

Commit

Permalink
Try to fix #4626, #4630 (start with failing tests) (#4635)
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder authored Jul 25, 2024
1 parent d8857c1 commit aafba87
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 8 deletions.
6 changes: 6 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ Project: jackson-databind
(reported by Eduard G)
#4617: Record property serialization order not preserved
(reported by @GeorgiPetkov)
#4626: `@JsonIgnore` on Record property ignored for deserialization, if
there is getter override
(reported by Sim Y-T)
#4630: `@JsonIncludeProperties`, `@JsonIgnoreProperties` ignored when serializing
Records, if there is getter override
(reported by Sim Y-T)
#4634: `@JsonAnySetter` not working when annotated on both constructor
parameter & field
(contributed by Sim Y-T)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,9 @@ protected void collectAll()
// altogether (unless we find a good reason to detect them)
// 17-Apr-2023: Need Records' fields for serialization for cases
// like [databind#3628], [databind#3895] and [databind#3992]
if (!isRecordType() || _forSerialization) {
_addFields(props); // note: populates _fieldRenameMappings
}
// 22-Jul-2024, tatu: ... and for deserialization sometimes too [databind#4626]
_addFields(props); // note: populates _fieldRenameMappings

_addMethods(props);
// 25-Jan-2016, tatu: Avoid introspecting (constructor-)creators for non-static
// inner classes, see [databind#1502]
Expand All @@ -455,7 +455,7 @@ protected void collectAll()
// since logic relies on knowing exactly which accessor has which annotation
_removeUnwantedProperties(props);
// and then remove unneeded accessors (wrt read-only, read-write)
_removeUnwantedAccessor(props);
_removeUnwantedAccessors(props);

// Rename remaining properties
_renameProperties(props);
Expand Down Expand Up @@ -485,6 +485,14 @@ protected void collectAll()
property.trimByVisibility();
}

// 22-Jul-2024, tatu: And now drop Record Fields once their effect
// (annotations) has been applied. But just for deserialization
if (_isRecordType && !_forSerialization) {
for (POJOPropertyBuilder property : props.values()) {
property.removeFields();
}
}

// and, if required, apply wrapper name: note, MUST be done after
// annotations are merged.
if (_config.isEnabled(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME)) {
Expand Down Expand Up @@ -1299,12 +1307,12 @@ protected void _removeUnwantedProperties(Map<String, POJOPropertyBuilder> props)
* based on read/write settings and rules for "pulling in" accessors
* (or not).
*/
protected void _removeUnwantedAccessor(Map<String, POJOPropertyBuilder> props)
protected void _removeUnwantedAccessors(Map<String, POJOPropertyBuilder> props)
{
// 15-Jan-2023, tatu: Avoid pulling in mutators for Records; Fields mostly
// since there should not be setters.
final boolean inferMutators = !isRecordType()
&& _config.isEnabled(MapperFeature.INFER_PROPERTY_MUTATORS);
// 22-Jul-2024, tatu: Actually do pull them to fix [databind#4630]
final boolean inferMutators = _config.isEnabled(MapperFeature.INFER_PROPERTY_MUTATORS);
Iterator<POJOPropertyBuilder> it = props.values().iterator();

while (it.hasNext()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,15 @@ public void removeConstructors() {
_ctorParameters = null;
}

/**
* Mutator that will simply drop any fields property may have.
*
* @since 2.18
*/
public void removeFields() {
_fields = null;
}

/**
* Method called to trim unnecessary entries, such as implicit
* getter if there is an explict one available. This is important
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void add(Recursion recursion) {

// [databind#3992]
@Test
public void testHelloRecord() throws Exception {
public void testHelloRecord3992() throws Exception {
Recursion beanWithRecursion = new Recursion();
beanWithRecursion.add(beanWithRecursion);
String json = MAPPER.writer()
Expand All @@ -50,4 +50,14 @@ public void testHelloRecord() throws Exception {
HelloRecord result = MAPPER.readValue(json, HelloRecord.class);
assertNotNull(result);
}

// [databind#4626]
@Test
public void testDeserializeWithOverride4626() throws Exception {
HelloRecord expected = new HelloRecord("hello", null);

assertEquals(expected, MAPPER.readValue(a2q("{'text':'hello'}"), HelloRecord.class));
assertEquals(expected, MAPPER.readValue(a2q("{'text':'hello','hidden':null}"), HelloRecord.class));
assertEquals(expected, MAPPER.readValue(a2q("{'text':'hello','hidden':{'all': []}}"), HelloRecord.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.fasterxml.jackson.databind.records;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonIncludeProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.testutil.DatabindTestUtil;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class RecordWithOverriddenInclude4630Test extends DatabindTestUtil
{
record Id2Name(int id, String name) {
}

record RecordWithJsonIncludeProperties(@JsonIncludeProperties("id") Id2Name child) {
@Override
public Id2Name child() {
return child;
}
}

record RecordWithJsonIgnoreProperties(@JsonIgnoreProperties("name") Id2Name child) {
@Override
public Id2Name child() {
return child;
}
}

private final ObjectMapper MAPPER = newJsonMapper();

// [databind#4630]
@Test
public void testSerializeJsonIncludeProperties() throws Exception {
String json = MAPPER.writeValueAsString(new RecordWithJsonIncludeProperties(new Id2Name(123, "Bob")));
assertEquals(a2q("{'child':{'id':123}}"), json);
}

// [databind#4630]
@Test
public void testSerializeJsonIgnoreProperties() throws Exception {
String json = MAPPER.writeValueAsString(new RecordWithJsonIgnoreProperties(new Id2Name(123, "Bob")));
assertEquals(a2q("{'child':{'id':123}}"), json);
}
}

0 comments on commit aafba87

Please sign in to comment.