Skip to content

Commit

Permalink
Add @Json.Creator (#189)
Browse files Browse the repository at this point in the history
* start

* test factory

* Update HybridBufferRecycler.java

* RC2

* doc

* constants are cool

* method reference
  • Loading branch information
SentryMan authored Nov 30, 2023
1 parent 1d6e20e commit 14c60f7
Show file tree
Hide file tree
Showing 20 changed files with 330 additions and 111 deletions.
2 changes: 1 addition & 1 deletion blackbox-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.avaje</groupId>
<artifactId>avaje-jsonb-parent</artifactId>
<version>1.10-RC1</version>
<version>1.10-RC2</version>
</parent>

<artifactId>blackbox-test</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion jsonb-generator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.avaje</groupId>
<artifactId>avaje-jsonb-parent</artifactId>
<version>1.10-RC1</version>
<version>1.10-RC2</version>
</parent>

<artifactId>avaje-jsonb-generator</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ public boolean hasJsonAnnotation() {

@Override
public void read() {

Optional.ofNullable(constructor)
.ifPresent(
c -> {
var enclosing = (TypeElement) c.element().getEnclosingElement();

importTypes.add(enclosing.getQualifiedName().toString());
});

importTypes.add(Util.shortName(type));
for (final FieldReader field : allFields) {
field.addImports(importTypes);
if (field.isRaw()) {
Expand Down Expand Up @@ -457,8 +467,9 @@ private void writeFromJsonImplementation(Append writer, String varName) {

private void writeJsonBuildResult(Append writer, String varName) {
writer.append(" // build and return %s", shortName).eol();
writer.append(" %s _$%s = new %s(", shortName, varName, shortName);
if (constructor != null) {
writer.append(" %s _$%s = " + constructor.creationString(), shortName, varName);

final List<MethodReader.MethodParam> params = constructor.getParams();
for (int i = 0, size = params.size(); i < size; i++) {
if (i > 0) {
Expand All @@ -470,6 +481,8 @@ private void writeJsonBuildResult(Append writer, String varName) {
// assuming name matches field here?
writer.append(constructorParamName(name + (frequency == 0 ? "" : frequency.toString())));
}
} else {
writer.append(" %s _$%s = new %s(", shortName, varName, shortName);
}
writer.append(");").eol();
for (final FieldReader allField : allFields) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.VariableElement;

import java.util.*;

final class FieldReader {
Expand All @@ -12,43 +14,74 @@ final class FieldReader {
private final FieldProperty property;
private final String propertyName;
private final boolean serialize;
private final boolean deserialize;
private boolean deserialize;
private final boolean unmapped;
private final boolean raw;

private final List<String> aliases;
private final List<String> aliases = new ArrayList<>();
private boolean isSubTypeField;
private final String num;
private boolean isCreatorParam;

FieldReader(
Element element,
NamingConvention namingConvention,
TypeSubTypeMeta subType,
List<String> genericTypeParams,
Integer frequency) {

FieldReader(Element element, NamingConvention namingConvention, TypeSubTypeMeta subType, List<String> genericTypeParams, Integer frequency) {
this(element, namingConvention, subType, genericTypeParams, frequency, false);
}

FieldReader(
Element element,
NamingConvention namingConvention,
TypeSubTypeMeta subType,
List<String> genericTypeParams,
Integer frequency,
boolean jsonCreatorPresent) {
num = frequency == 0 ? "" : frequency.toString();
addSubType(subType);
final PropertyIgnoreReader ignoreReader = new PropertyIgnoreReader(element);
this.unmapped = ignoreReader.unmapped();
var isMethod = element instanceof ExecutableElement;
this.raw = ignoreReader.raw();
this.serialize = ignoreReader.serialize();
this.deserialize = !isMethod && ignoreReader.deserialize();
var isParam = element.getEnclosingElement() instanceof ExecutableElement;
this.unmapped = UnmappedPrism.isPresent(element);
this.raw = RawPrism.isPresent(element);
this.serialize = !isParam && ignoreReader.serialize();
this.deserialize = isParam || !jsonCreatorPresent && !isMethod && ignoreReader.deserialize();

final var fieldName = element.getSimpleName().toString();
final var publicField = !isMethod && element.getModifiers().contains(Modifier.PUBLIC);
final var publicField =
!isMethod && !isParam && element.getModifiers().contains(Modifier.PUBLIC);
final var type = isMethod ? ((ExecutableElement) element).getReturnType() : element.asType();

this.property = new FieldProperty(type, raw, unmapped, genericTypeParams, publicField, fieldName);
this.propertyName = PropertyPrism.getOptionalOn(element)
.map(PropertyPrism::value)
.map(Util::escapeQuotes)
.orElse(namingConvention.from(fieldName));
this.property =
new FieldProperty(type, raw, unmapped, genericTypeParams, publicField, fieldName);
this.propertyName =
PropertyPrism.getOptionalOn(element)
.map(PropertyPrism::value)
.map(Util::escapeQuotes)
.orElse(namingConvention.from(fieldName));

initAliases(element);
}

this.aliases = initAliases(element);
public void readParam(VariableElement element) {
this.deserialize = true;
this.isCreatorParam = true;
initAliases(element);
}

private static List<String> initAliases(Element element) {
return AliasPrism.getOptionalOn(element)
.map(a -> Util.escapeQuotes(a.value()))
.orElse(JsonAliasPrism.getOptionalOn(element)
.map(a -> Util.escapeQuotes(a.value()))
.orElse(Collections.emptyList()));
private void initAliases(Element element) {
var alias =
AliasPrism.getOptionalOn(element)
.map(a -> Util.escapeQuotes(a.value()))
.orElse(
JsonAliasPrism.getOptionalOn(element)
.map(a -> Util.escapeQuotes(a.value()))
.orElse(Collections.emptyList()));

aliases.addAll(alias);
}

void position(int pos) {
Expand Down Expand Up @@ -203,6 +236,7 @@ void writeFromJsonSwitch(Append writer, boolean defaultConstructor, String varNa
}

void writeFromJsonSetter(Append writer, String varName, String prefix) {
if (isCreatorParam) return;
property.writeFromJsonSetter(writer, varName, prefix, num);
}

Expand Down Expand Up @@ -243,6 +277,10 @@ public void setSetter(MethodReader setter) {
property.setSetterMethod(setter);
}

public void setDeserialize(boolean deserialize) {
this.deserialize = deserialize;
}

public boolean isDeserialize() {
return deserialize;
}
Expand All @@ -254,4 +292,5 @@ public Map<String, TypeSubTypeMeta> subTypes() {
public List<String> aliases() {
return aliases;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.avaje.jsonb.generator;

import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
Expand All @@ -14,7 +15,7 @@ final class MethodReader {
private final String methodName;
private final List<MethodParam> params = new ArrayList<>();

MethodReader(ExecutableElement element, TypeElement beanType) {
MethodReader(ExecutableElement element) {
this.element = element;
this.methodName = element.getSimpleName().toString();
}
Expand Down Expand Up @@ -44,7 +45,6 @@ List<MethodParam> getParams() {
return params;
}


public boolean isPublic() {
return element.getModifiers().contains(Modifier.PUBLIC);
}
Expand All @@ -53,14 +53,31 @@ public boolean isProtected() {
return element.getModifiers().contains(Modifier.PROTECTED);
}

public String creationString() {
var shortName =
Util.shortName(((TypeElement) element.getEnclosingElement()).getQualifiedName().toString());

if (element.getKind() == ElementKind.CONSTRUCTOR) {
return String.format("new %s(", shortName);
}

return String.format("%s.%s(", shortName, element.getSimpleName());
}

public ExecutableElement element() {
return element;
}

static class MethodParam {

private final String simpleName;
private final String type;
private final VariableElement element;

MethodParam(VariableElement param) {
this.simpleName = param.getSimpleName().toString();
this.type = param.asType().toString();
element = param;
}

String name() {
Expand All @@ -70,5 +87,13 @@ String name() {
public String type() {
return type;
}

public VariableElement element() {
return element;
}

public VariableElement getElement() {
return element;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@

final class PropertyIgnoreReader {

private final boolean unmapped;
private final boolean raw;
private boolean ignoreSerialize;
private boolean ignoreDeserialize;

PropertyIgnoreReader(Element element) {
unmapped = UnmappedPrism.isPresent(element) ;
raw = RawPrism.isPresent(element);

final IgnorePrism ignored = IgnorePrism.getInstanceOn(element);
if (ignored != null) {
Expand All @@ -20,14 +16,6 @@ final class PropertyIgnoreReader {
}
}

boolean unmapped() {
return unmapped;
}

boolean raw() {
return raw;
}

boolean serialize() {
return !ignoreSerialize;
}
Expand Down
Loading

0 comments on commit 14c60f7

Please sign in to comment.