jackson-databind
jackson-databind copied to clipboard
Support specifying method for instantiating builders in JsonDeserialize
I request adding a parameter such as builderMethod
to JsonDeserialize
(e.g. @JsonDeserialize(builderMethod = "builder")
) to facilitate a way of specifying a method to instantiate a builder instance.
Example use case When using the Lombok SuperBuilder annotation it results in the creation two builder inner classes, one public and the other private which subclasses the public; it is the private class that must be instantiated. Currently when using the SuperBuilder annotation it is necessary to declare the private inner class (which will be completed during the annotation processing stage) to set its access modifier to package private so that Jackson can instantiated it.
An example original source file and the annotation processed result follows:
Original file
@JsonDeserialize(builder = LegalDocument.LegalDocumentBuilderImpl.class)
@Getter
@SuperBuilder(toBuilder = true)
public final class LegalDocument {
private final String code;
private final String fileName;
private final String description;
// This should not be necessary
static final class LegalDocumentBuilderImpl
extends LegalDocument.LegalDocumentBuilder<
LegalDocument, LegalDocumentBuilderImpl> {
}
}
After annotation processing
@JsonDeserialize(
builder = LegalDocument.LegalDocumentBuilderImpl.class
)
public final class LegalDocument {
private final String code;
private final String fileName;
private final String description;
@Generated
protected LegalDocument(LegalDocument.LegalDocumentBuilder<?, ?> b) {
this.code = b.code;
this.fileName = b.fileName;
this.description = b.description;
}
// I would like to be able reference this method in the JsonDerserialize annotation
@Generated
public static LegalDocument.LegalDocumentBuilder<?, ?> builder() {
return new LegalDocument.LegalDocumentBuilderImpl();
}
@Generated
public LegalDocument.LegalDocumentBuilder<?, ?> toBuilder() {
return (new LegalDocument.LegalDocumentBuilderImpl()).$fillValuesFrom(this);
}
@Generated
public String getCode() {
return this.code;
}
@Generated
public String getFileName() {
return this.fileName;
}
@Generated
public String getDescription() {
return this.description;
}
@Generated
public abstract static class LegalDocumentBuilder<C extends LegalDocument, B extends LegalDocument.LegalDocumentBuilder<C, B>> {
@Generated
private String code;
@Generated
private String fileName;
@Generated
private String description;
public LegalDocumentBuilder() {
}
@Generated
protected B $fillValuesFrom(C instance) {
$fillValuesFromInstanceIntoBuilder(instance, this);
return this.self();
}
@Generated
private static void $fillValuesFromInstanceIntoBuilder(LegalDocument instance, LegalDocument.LegalDocumentBuilder<?, ?> b) {
b.code(instance.code);
b.fileName(instance.fileName);
b.description(instance.description);
}
@Generated
protected abstract B self();
@Generated
public abstract C build();
@Generated
public B code(String code) {
this.code = code;
return this.self();
}
@Generated
public B fileName(String fileName) {
this.fileName = fileName;
return this.self();
}
@Generated
public B description(String description) {
this.description = description;
return this.self();
}
@Generated
public String toString() {
return "LegalDocument.LegalDocumentBuilder(code=" + this.code + ", fileName=" + this.fileName + ", description=" + this.description + ")";
}
}
static final class LegalDocumentBuilderImpl extends LegalDocument.LegalDocumentBuilder<LegalDocument, LegalDocument.LegalDocumentBuilderImpl> {
@Generated
private LegalDocumentBuilderImpl() {
}
@Generated
protected LegalDocument.LegalDocumentBuilderImpl self() {
return this;
}
@Generated
public LegalDocument build() {
return new LegalDocument(this);
}
}
}