FasterXML / FasterXML/jackson-databind

`@JacksonInject(useInput = OptBoolean.FALSE)` ignored for Field and Setter properties

Open
#6,201 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
3.7k
Forks
1.5k
Avg merge
3d 6h
Merged PRs (30d)
28

Description

### Search before asking

- [X] I searched in the [issues](https://github.com/FasterXML/jackson-databind/issues) and found nothing similar.

### Describe the bug

`@JacksonInject` documents `useInput = OptBoolean.FALSE` as "input value (if any) will be ignored", and the `@return` javadoc spells it out further: "`OptBoolean.FALSE` if injected value will always be used regardless of input".

That holds for Creator properties. `CreatorProperty.isInjectionOnly()` reports it and the property-based-Creator loops act on it (the `[databind#1381]` checks in `BeanDeserializer`, `BuilderBasedDeserializer`, `BeanAsArrayDeserializer` and `BeanAsArrayBuilderDeserializer`), with `PropertyValueBuffer._inject()` supplying the value afterwards.

It does not hold for a property backed by a Field or a Setter. `SettableBeanProperty.getInjectionDefinition()` returns `null` for those, so `isInjectionOnly()` is always false and the property stays in the settable set. Injection for them goes through `ValueInjector` instead, and `injectValues()` runs right after the bean is constructed, before any property is read, so a matching name in the document just overwrites the injected value.

The practical consequence is for code that uses `@JacksonInject` to pin a server-side value onto a POJO, say a tenant id, a principal, or a request id: with `useInput = OptBoolean.FALSE` the caller has asked for that value to be non-overridable, and the document overrides it anyway.

`JacksonInject1381Test` already asserts the intended behavior ("input YES, injectable YES, useInput DEFAULT|FALSE => injected"), but every fixture in it reaches the value through a Creator, so the Field/Setter path is not covered.

### Version Information

3.1, 3.2, 3.x (also 2.22.2)

### Reproduction

```java
public class Doc {
@JacksonInject(value = "tenant", useInput = OptBoolean.FALSE)
public String tenant = "unset";

public String title = "";
}

ObjectMapper mapper = JsonMapper.builder()
.injectableValues(new InjectableValues.Std().addValue("tenant", "tenant-42"))
.build();

Doc doc = mapper.readValue("{\"tenant\":\"tenant-99\",\"title\":\"x\"}", Doc.class);

System.out.println(doc.tenant); // prints "tenant-99", expected "tenant-42"
```

The same holds for a `@JacksonInject`-annotated setter, for `@JsonFormat(shape = Shape.ARRAY)` types, for `@JsonPOJOBuilder` builders, for `@JsonUnwrapped` values, and on the `readerForUpdating()` path.

Moving the same declaration onto a Creator parameter gives the documented result:

```java
public class Doc {
public final String tenant;
public final String title;

@JsonCreator
public Doc(@JacksonInject(value = "tenant", useInput = OptBoolean.FALSE) String tenant,
@JsonProperty("title") String title) {
this.tenant = tenant;
this.title = title;
}
}
// doc.tenant is "tenant-42"
```

### Expected behavior

A Field- or Setter-backed property annotated with `@JacksonInject(useInput = OptBoolean.FALSE)` should keep the injected value and drop any matching value from input, the same as the Creator case.

Only the explicit `OptBoolean.FALSE` setting is at issue here. `DEFAULT` and `TRUE` should keep behaving as they do now.

### Additional context

Related: #1381 (where `useInput` handling was introduced) and #2678.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with SettableBeanProperty.getInjectionDefinition(), ValueInjector.injectValues(), and the injection-only checks described in BeanDeserializer and related deserializers. Read JacksonInject1381Test first, then cover Field- and Setter-backed properties, including the listed array, builder, unwrapped, and updating paths. Done means explicit FALSE preserves the injected value while DEFAULT and TRUE retain current behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.