Search before asking
Describe the bug
MapperFeature.DETECT_PARAMETER_NAMES was added in #5314 as an opt-out for the Jackson-3-only behavior where constructor/factory-method parameter names are inferred from compiled -parameters bytecode (previously the separate jackson-parameter-names module in Jackson 2).
Disabling this feature also silently disables implicit-name resolution via @ConstructorProperties, an older and completely independent JavaBeans mechanism that has nothing to do with -parameters bytecode metadata. This worked fine in Jackson 2 regardless of whether jackson-parameter-names was registered.
The cause is in JacksonAnnotationIntrospector.findImplicitPropertyName():
the DETECT_PARAMETER_NAMES check is a single early-return placed before the method checks for @ConstructorProperties, so disabling the flag also kills the annotation-based path, not just the bytecode-based one:
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; // <-- returns before ever checking @ConstructorProperties
}
if (m instanceof AnnotatedParameter p) {
AnnotatedWithParams owner = p.getOwner();
if (owner instanceof AnnotatedConstructor) {
if (_javaBeansHelper != null) {
PropertyName name = _javaBeansHelper.findConstructorName(p); // @ConstructorProperties
...
}
return _findImplicitName(owner, p.getIndex()); // -parameters bytecode
}
...
This affects any class using @ConstructorProperties — notably Lombok output when lombok.anyConstructor.addConstructorProperties=true is set — as soon as a consumer disables DETECT_PARAMETER_NAMES for any reason (e.g. Jackson 2 behavior parity, or avoiding reliance on -parameters compilation).
Version Information
3.x (3.3.0-SNAPSHOT, current 3.x branch HEAD)
Reproduction
import java.beans.ConstructorProperties;
import tools.jackson.databind.MapperFeature;
import tools.jackson.databind.json.JsonMapper;
public class Repro {
static class CtorPropsDto {
public final int id;
public final String name;
@ConstructorProperties({"id", "name"})
public CtorPropsDto(int id, String name) {
this.id = id;
this.name = name;
}
}
public static void main(String[] args) {
JsonMapper mapper = JsonMapper.builder()
.disable(MapperFeature.DETECT_PARAMETER_NAMES)
.build();
// throws InvalidDefinitionException: "... has no property name
// (and is not Injectable): cannot use as property-based Creator"
mapper.readValue("{\"id\":1,\"name\":\"x\"}", CtorPropsDto.class);
}
}
Expected behavior
@ConstructorProperties-annotated constructors should keep resolving implicit parameter names regardless of DETECT_PARAMETER_NAMES, since that flag's documented purpose (see its Javadoc and the original request in #5314) is
scoped to the bytecode/-parameters behavior merged from the old jackson-parameter-names module, not to @ConstructorProperties, which predates and is independent of it.
Additional context
I have a minimal, scoped fix ready (moves the DETECT_PARAMETER_NAMES check to only guard the bytecode-based fallback branch, leaving the @ConstructorProperties branch unconditional) plus regression tests covering:
@ConstructorProperties still works with the flag enabled (baseline, unchanged)
@ConstructorProperties now works with the flag disabled (the fix)
- a bytecode-only constructor (no
@ConstructorProperties) is still correctly
suppressed when the flag is disabled (guard rail against over-fixing)
The fix is contained here: #6230
Let me know if I can provide anything else to help this move forward! 😄
Search before asking
Describe the bug
MapperFeature.DETECT_PARAMETER_NAMESwas added in #5314 as an opt-out for the Jackson-3-only behavior where constructor/factory-method parameter names are inferred from compiled-parametersbytecode (previously the separatejackson-parameter-namesmodule in Jackson 2).Disabling this feature also silently disables implicit-name resolution via
@ConstructorProperties, an older and completely independent JavaBeans mechanism that has nothing to do with-parametersbytecode metadata. This worked fine in Jackson 2 regardless of whetherjackson-parameter-nameswas registered.The cause is in
JacksonAnnotationIntrospector.findImplicitPropertyName():the
DETECT_PARAMETER_NAMEScheck is a single early-return placed before the method checks for@ConstructorProperties, so disabling the flag also kills the annotation-based path, not just the bytecode-based one:This affects any class using
@ConstructorProperties— notably Lombok output whenlombok.anyConstructor.addConstructorProperties=trueis set — as soon as a consumer disablesDETECT_PARAMETER_NAMESfor any reason (e.g. Jackson 2 behavior parity, or avoiding reliance on-parameterscompilation).Version Information
3.x (
3.3.0-SNAPSHOT, current3.xbranch HEAD)Reproduction
Expected behavior
@ConstructorProperties-annotated constructors should keep resolving implicit parameter names regardless ofDETECT_PARAMETER_NAMES, since that flag's documented purpose (see its Javadoc and the original request in #5314) isscoped to the bytecode/
-parametersbehavior merged from the oldjackson-parameter-namesmodule, not to@ConstructorProperties, which predates and is independent of it.Additional context
I have a minimal, scoped fix ready (moves the
DETECT_PARAMETER_NAMEScheck to only guard the bytecode-based fallback branch, leaving the@ConstructorPropertiesbranch unconditional) plus regression tests covering:@ConstructorPropertiesstill works with the flag enabled (baseline, unchanged)@ConstructorPropertiesnow works with the flag disabled (the fix)@ConstructorProperties) is still correctlysuppressed when the flag is disabled (guard rail against over-fixing)
The fix is contained here: #6230
Let me know if I can provide anything else to help this move forward! 😄