Skip to content

Consider possibility of allowing "delegating-AND-properties-based" Creators #5084

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
cowtowncoder opened this issue Apr 10, 2025 · 5 comments
Labels
2.19 Issues planned at 2.19 or later

Comments

@cowtowncoder
Copy link
Member

cowtowncoder commented Apr 10, 2025

A recurring use case for value classes is that of wanting to support two related structures for deserialization via Creator methods (constructor / factory method). Basically to allow 2 JSON structures like so:

123

{ "value": 123 }

Initial attempt seems to regularly be to just try single constructor

class ValueType {
   private int value;

  @JsonCreator
  public ValueType(int value) {
    this.value = value;
  }
}

and hope/expect it works. I think both #2135 and #3210 (just as examples -- there are many more).

This does not work, currently, because Jackson requires every Creator to be of exactly one type: for 1-argument Creators either:

  1. "DELEGATING" -- incoming JSON Value is bound exactly as-is to parameter, using its type
  2. "PROPERTIES"-based -- incoming JSON Value must be Object, with 1 entry, with its name matching parameter name; and then its value is bound to parameter, using its type.

In earlier example, then:

  • JSON value 123 works if (and only if) using mode = Mode.DELEGATING
  • JSON value {"value": 123} works if (and only if) using mode = Mode.PROPERTIES

and the trickiest case is one where no mode is specified: databind will then try to essentially guess which mode to use -- and this at Deserializer constructor time having only access to Class definition and not JSON value at all (by the time JSON is available, Creators have been long since resolved).

So as things are, one MUST define 2 separate Creators: usually one Constructor and one Factory method (one delegating, the other properties based). So like this:

class ValueType {
   private int value;

  @JsonCreator(mode = Mode.DELEGATING)
  public ValueType(int value) {
    this.value = value;
  }

  @JsonCreator // mode optional due to annotation (mode = Mode.PROPERTIES)
  static ValueType of(@JsonProperty("value") int value) {
     return new ValueType(value);
  }
}

But what if we had theoretical Mode.DELEGATING_AND_PROPERTIES, used like this:

class ValueType {
   private int value;

  @JsonCreator(mode = JsonCreator.Mode.DELEGATING_AND_PROPERTIES`
  public ValueType(@JsonProperty("value") int value) {
    this.value = value;
  }
}

which would actually support both cases with one Creator?

Internally this could be done by basically constructing 2 Creator entities, but with same actual underlying constructor (or factory method).

In fact, if this works, maybe we could even allow auto-detection? If so, then any 1-parameter Creator that qualifies as Properties-based, could ALSO be detected as Delegating if (and only if) there is no explicitly annotated Delegating creator.
But maybe it is better to consider one step at a time, support explicit "dual-mode".

So, would this be a good idea?

@cowtowncoder cowtowncoder added the 2.19 Issues planned at 2.19 or later label Apr 10, 2025
@cowtowncoder
Copy link
Member Author

cc @JooHyukKim

@JooHyukKim
Copy link
Member

JooHyukKim commented Apr 10, 2025

Sounds like a useful thing to have for users. Can we go further and...

  • In Jackson 2, user should specify Mode.DELEGATING_OR_PROPERTIES
  • In Jackon 3, make Mode.DEFAULT work as DELEGATING_OR_PROPERTIES

... do this?

@yihtserns
Copy link
Contributor

(just like how the title is written, shouldn't this be Mode.DELEGATING_**AND**_PROPERTIES?)

@cowtowncoder
Copy link
Member Author

cowtowncoder commented Apr 10, 2025

Good point -- either would work but maybe "AND" is better. As long as we use whichever conjunctive consistently. So let's go with "and".
Will update accordingly.

@JooHyukKim Yes, start with explicit, see if we can make implicit work for 3.0.

@JooHyukKim
Copy link
Member

Filed FasterXML/jackson-annotations#288 for a start.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.19 Issues planned at 2.19 or later
Projects
None yet
Development

No branches or pull requests

3 participants