FasterXML / FasterXML/jackson-databind

Support factories (external factory methods)

Open
#3,472 2 comments 9 reactions 0 assignees View on GitHub
most-wanted pr-welcome
Dominant language
Java
Stars
3.7k
Forks
1.5k
Avg merge
3d 6h
Merged PRs (30d)
28

Description

**Feature**
Support static factory methods in factory classes.
The factory method should be able to accept properties like a class-local creator method.

**Problem solved**
Currently a creator method must be within the same class.
Factory methods in other classes are not supported.
Thus, if the constructor of a non-modifiable class (e.g. from a library) is non-accessible and the factory method is in another class, the only workaround is to use CAN_OVERRIDE_ACCESS_MODIFIERS, which is not possible in some environments.

Examples classes that cannot be deserialized currently in environments, where access modifiers cannot be overridden:
* Creation via factory:
```java
public class ClassWithoutAccessibleConstructor {
...
}

public FactoryForClassWithoutAccessibleConstructor {
public static createClassWithoutAccessibleConstructor() {
...
}
}
```
* Class with Builder without public constructor:
```java
public class ClassWithBuilder {
public static builder() {
return new BuilderWithoutPublicConstructor();
}

public static class BuilderWithoutPublicConstructor {
}
}
```

**Proposed implementation**
* extend the @JsonDeserialize annotation by a factory property
* use @JsonCreator in the factory to mark the factory method
* use @JsonProperty to mark factory method parameters
* Mixins are supported for factories, too, to allow configuration, if the factory class cannot be changed

**Usage example:**
* class with unaccessible constructor and factory
```java
@JsonDeserialize(factory = MyFactory.class)
public class MyBean {
...
}

public class MyFactory {
@JsonCreator
public static MyBean createMyBean(@JsonProperty(...) ...) {
...
}
}
```
* class with builder that has an unaccessible constructor
```java
@JsonDeserialize(builder = MyBuilder.class)
public class MyBean {
...
@JsonCreator
public static MyBuilder builder() {
return new MyBuilder();
}

@JsonPOJOBuilder
@JsonDeserialize(factory = MyBean.class)
public static class MyBuilder {
...
}
}
```

**Additional context**
* in the second example the bean is at the same time a factory for the builder. If this makes implementation too difficult and will not be allowed, it is easy to implement a simple factory that just calls the bean's builder factory method instead.
* in the same way it is not necessary to support non-static factory methods, as it is easy to create a new custom factory class with a method that constructs the factory and delegates to the non-static method.
* this feature request can also solve issue #1820, by using the mixin as factory, too, e.g.:
```java
@JsonDeserialize(factory = MyBeanMixin.class)
public class MyBeanMixin {
@JsonCreator
public static createBean(@JsonProperty(...) ...) {
...
}
}
```
* this feature request also solves issue #2354 as shown in second example.
* this feature request also supports a work around for #3041, namely creating a factory method with all parameters of the available constructors, which then decides, which constructor to call.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.