Skip to content

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

Open
@cowtowncoder

Description

@cowtowncoder

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    2.19Issues planned at 2.19 or later

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions