Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions release-notes/CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -746,3 +746,8 @@ Sergey Lappo (@sergeylappo)
* Reported #6227: `BeanDescription` is not thread-safe when called concurrently on the
same instance (`findProperties()`, `findDefaultViews()`)
[3.2.4]

Mauricio Souza (@mauriciocsz)
* Reported, contributed fix for #6229: `DETECT_PARAMETER_NAMES` disabled also prevents
`@ConstructorProperties` based Creator detection
[3.3.0]
3 changes: 3 additions & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ Versions: 3.x (for earlier see VERSION-2.x)
(Default Typing, `@JsonTypeInfo`) resolves a type id: type deserializer was built
for the declared type, before the refinement
(fix by @pjfanning)
#6229: `DETECT_PARAMETER_NAMES` disabled also prevents `@ConstructorProperties`
based Creator detection
(fix by @mauriciocsz)
#6231: Add copy constructor for `JacksonAnnotationIntrospector` (for sub-classes
to create re-configured copies)
(fix by @cowtowncoder, w/ Claude code)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,10 @@ public VisibilityChecker findAutoDetectVisibility(MapperConfig<?> config,
@Override
public String findImplicitPropertyName(MapperConfig<?> config, AnnotatedMember m)
{
// 15-Sep-2025: As per [databind#5314] possible to disable introspection
if (!config.isEnabled(MapperFeature.DETECT_PARAMETER_NAMES)) {
return null;
}
if (m instanceof AnnotatedParameter p) {
// 15-Sep-2025: As per [databind#5314] possible to disable introspection
final boolean detectParamNames = config.isEnabled(MapperFeature.DETECT_PARAMETER_NAMES);

AnnotatedWithParams owner = p.getOwner();
if (owner instanceof AnnotatedConstructor) {
// 15-Sep-2025, tatu: May seem odd but we'll keep access dynamic due
Expand All @@ -383,12 +382,15 @@ public String findImplicitPropertyName(MapperConfig<?> config, AnnotatedMember m
}
}
// ... or parameter names from bytecode (JDK8)
return _findImplicitName(owner, p.getIndex());
if (detectParamNames) {
return _findImplicitName(owner, p.getIndex());
}
return null;
}
if (owner instanceof AnnotatedMethod) {
// For now let's only bother discovering names for static methods as they
// (only) may be creators
if (owner.isStatic()) {
if (detectParamNames && owner.isStatic()) {
return _findImplicitName(owner, p.getIndex());
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package tools.jackson.databind.deser;

import java.beans.ConstructorProperties;

import org.junit.jupiter.api.Test;

import tools.jackson.databind.MapperFeature;
Expand Down Expand Up @@ -27,6 +29,21 @@ public Bean178(String openName, int openAge) {
}
}

// [databind#6229]: same shape as Bean178 above, but with `@ConstructorProperties`
// added -- specifically to validate Jackson 2.x compatibility, `@ConstructorProperties`
// must keep resolving names regardless of `DETECT_PARAMETER_NAMES`.
static class CtorPropsBean6229
{
final String hiddenName;
final int hiddenAge;

@ConstructorProperties({"openName", "openAge"})
public CtorPropsBean6229(String openName, int openAge) {
hiddenName = openName;
hiddenAge = openAge;
}
}

private final String JSON = a2q("{'openName':'stu','openAge':22}");

@Test
Expand All @@ -46,10 +63,29 @@ public void testWorksByDefault()
.builderWithJackson2Defaults().build());
}

// [databind#6229]: `CtorPropsBean178` (see above) must deserialize
// successfully under all three configs below.
@Test
public void testConstructorPropertiesIgnoresDetectParameterNames()
{
_runCtorPropsSuccess(JsonMapper.builder()
.enable(MapperFeature.DETECT_PARAMETER_NAMES).build());
_runCtorPropsSuccess(JsonMapper.builder()
.disable(MapperFeature.DETECT_PARAMETER_NAMES).build());
_runCtorPropsSuccess(JsonMapper
.builderWithJackson2Defaults().build());
}

private void _runTestSuccess(JsonMapper mapper)
{
Bean178 bean = mapper.readValue(JSON, Bean178.class);
assertEquals("stu", bean.hiddenName);
assertEquals(22, bean.hiddenAge);
}

private void _runCtorPropsSuccess(JsonMapper mapper)
{
CtorPropsBean6229 bean = mapper.readValue(JSON, CtorPropsBean6229.class);
assertEquals("stu", bean.hiddenName);
assertEquals(22, bean.hiddenAge);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

package tools.jackson.databind.deser.creators;

import java.io.IOException;
import java.util.List;
import java.util.Map;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;

// For [databind#2816] / [databind#3473]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

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

// for [databind#2900]
public class Java9ListsTest extends DatabindTestUtil
Expand Down