Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -403,20 +403,21 @@ private static MethodSpec createConstructorBasedParseMethod(final Class<?> targe
*/
private static String generateFieldParsingCode(final MethodSpec.Builder methodBuilder, final Field field,
final String parserPackage) {
final String jsonKey = ParserCommonUtils.jsonKeyFor(field);
methodBuilder.addCode("\n");
methodBuilder.addComment("Parse $L", field.getName());

// Check if field is required (must exist in JSON)
methodBuilder.beginControlFlow("if (!$L.has($S))", ParserCommonUtils.BASE_OBJECT_PARAM_NAME, field.getName())
methodBuilder.beginControlFlow("if (!$L.has($S))", ParserCommonUtils.BASE_OBJECT_PARAM_NAME, jsonKey)
.addStatement("throw new $T($S)", RuntimeException.class,
"Required field '" + field.getName() + "' is missing")
"Required field '" + jsonKey + "' is missing")
.endControlFlow();

// Create access expression for this field
final CodeBlock fieldAccess = ParserCommonUtils.createFieldAccessCode(
field.getGenericType(),
ParserCommonUtils.BASE_OBJECT_PARAM_NAME,
CodeBlock.of("$S", field.getName()));
CodeBlock.of("$S", jsonKey));

// Use existing TypeParser infrastructure to generate parsing code with field name as variable name
final CodeBlock.Builder parseCode = CodeBlock.builder();
Expand Down Expand Up @@ -454,18 +455,19 @@ private static MethodSpec createConfigParseMethod(final Class<?> targetClass, fi
}

for (final Field field : ConstructorAnalyzer.getParseableFields(targetClass)) {
final String jsonKey = ParserCommonUtils.jsonKeyFor(field);
methodBuilder.addCode("\n");
methodBuilder.addComment("Parse $L", field.getName());
final boolean requireNonNull = !ParserCommonUtils.isPrimitiveType(field.getGenericType());
methodBuilder.addCode(ParserCommonUtils.createFieldExistsCheck(
ParserCommonUtils.BASE_OBJECT_PARAM_NAME,
field.getName(),
jsonKey,
requireNonNull,
innerCode -> {
final CodeBlock fieldAccess = ParserCommonUtils.createFieldAccessCode(
field.getGenericType(),
ParserCommonUtils.BASE_OBJECT_PARAM_NAME,
CodeBlock.of("$S", field.getName()));
CodeBlock.of("$S", jsonKey));

final String resultVar = dispatchGenerateParsingCodeInto(
innerCode,
Expand All @@ -475,7 +477,7 @@ private static MethodSpec createConfigParseMethod(final Class<?> targetClass, fi
fieldAccess,
1,
field.getGenericType());
innerCode.addStatement("config.set$L($L)", ParserCommonUtils.capitalize(field.getName()), resultVar);
innerCode.addStatement("config.set$L($L)", ParserCommonUtils.capitalize(jsonKey), resultVar);
}));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package nl.aerius.codegen.generator.parser;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
Expand All @@ -11,6 +12,7 @@

import javax.annotation.processing.Generated;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.palantir.javapoet.AnnotationSpec;
import com.palantir.javapoet.ClassName;
import com.palantir.javapoet.CodeBlock;
Expand Down Expand Up @@ -115,6 +117,14 @@ public static String stripGenerics(final String typeName) {
return (genericStart < 0 ? typeName : typeName.substring(0, genericStart)).trim();
}

public static String jsonKeyFor(final Field field) {
final JsonProperty ann = field.getAnnotation(JsonProperty.class);
if (ann != null && !ann.value().isEmpty()) {
return ann.value();
}
return field.getName();
}

/**
* Capitalizes the first letter of a string.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import nl.aerius.codegen.analyzer.ConstructorAnalyzer;
import nl.aerius.codegen.analyzer.TypeAnalyzer;
import nl.aerius.codegen.generator.parser.ParserCommonUtils;
import nl.aerius.codegen.util.ClassFinder;
import nl.aerius.codegen.util.FileUtils;
import nl.aerius.codegen.util.Logger;
Expand Down Expand Up @@ -425,7 +426,7 @@ private boolean validateGetterSetter(final Class<?> clazz, final Field field, fi
return true;
}
final String fieldName = field.getName();
final String capitalizedName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
final String capitalizedName = ParserCommonUtils.capitalize(ParserCommonUtils.jsonKeyFor(field));
boolean isValid = true;
final String prefix = treatErrorsAsWarnings ? WARNING : RED_CROSS;

Expand Down Expand Up @@ -480,18 +481,20 @@ private boolean validateGetterSetter(final Class<?> clazz, final Field field, fi
return isValid;
}

// Check setter for non-constructor-based types
final String setterName = "set" + capitalizedName;
try {
final Method setter = clazz.getMethod("set" + capitalizedName, field.getType());
final Method setter = clazz.getMethod(setterName, field.getType());
if (!Modifier.isPublic(setter.getModifiers())) {
logger.warn(prefix + " " + clazz.getName() + ": Field '" + fieldName + "' must have a public setter (setter not public)");
logger.warn(prefix + " " + clazz.getName() + ": Field '" + fieldName + "' must have a public setter '" + setterName
+ "' (setter not public)");
if (!treatErrorsAsWarnings) {
hasErrors = true;
}
isValid = false;
}
} catch (final NoSuchMethodException e) {
logger.warn(prefix + " " + clazz.getName() + ": Field '" + fieldName + "' must have a public setter (setter not found)");
logger.warn(prefix + " " + clazz.getName() + ": Field '" + fieldName + "' must have a public setter '" + setterName
+ "' (setter not found)");
if (!treatErrorsAsWarnings) {
hasErrors = true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package nl.aerius.codegen.test.types;

import com.fasterxml.jackson.annotation.JsonProperty;

public class TestJsonPropertyRenameType {
@JsonProperty("id")
private int assessmentAreaId;
private String name;

public int getId() {
return assessmentAreaId;
}

public void setId(final int id) {
Comment thread
JornC marked this conversation as resolved.
this.assessmentAreaId = id;
}

public String getName() {
return name;
}

public void setName(final String name) {
this.name = name;
}

public static TestJsonPropertyRenameType createFullObject() {
final TestJsonPropertyRenameType obj = new TestJsonPropertyRenameType();
obj.setId(42);
obj.setName("Veluwe");
return obj;
}

public static TestJsonPropertyRenameType createNullObject() {
final TestJsonPropertyRenameType obj = new TestJsonPropertyRenameType();
obj.setName(null);
return obj;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class TestRootObjectType {
private TestConstructorWithGenericsType constructorWithGenerics;
private TestConstructorWithIgnoredFieldType constructorWithIgnoredField;
private TestRecordType recordType;
private TestJsonPropertyRenameType jsonPropertyRename;

public String getFoo() {
return foo;
Expand Down Expand Up @@ -171,6 +172,14 @@ public void setRecordType(TestRecordType recordType) {
this.recordType = recordType;
}

public TestJsonPropertyRenameType getJsonPropertyRename() {
return jsonPropertyRename;
}

public void setJsonPropertyRename(TestJsonPropertyRenameType jsonPropertyRename) {
this.jsonPropertyRename = jsonPropertyRename;
}

public static TestRootObjectType createFullObject() {
TestRootObjectType obj = new TestRootObjectType();
obj.setFoo("test string");
Expand All @@ -191,6 +200,7 @@ public static TestRootObjectType createFullObject() {
obj.setConstructorWithGenerics(TestConstructorWithGenericsType.createFullObject());
obj.setConstructorWithIgnoredField(TestConstructorWithIgnoredFieldType.createFullObject());
obj.setRecordType(TestRecordType.createFullObject());
obj.setJsonPropertyRename(TestJsonPropertyRenameType.createFullObject());
return obj;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package nl.aerius.codegen.test.generated;

import javax.annotation.processing.Generated;

import nl.aerius.codegen.test.types.TestJsonPropertyRenameType;
import nl.aerius.json.JSONObjectHandle;

@Generated(value = "nl.aerius.codegen.ParserGenerator", date = "2024-01-01T00:00:00")
public class TestJsonPropertyRenameTypeParser {
public static TestJsonPropertyRenameType parse(final String jsonText) {
if (jsonText == null) {
return null;
}

return parse(JSONObjectHandle.fromText(jsonText));
}

public static TestJsonPropertyRenameType parse(final JSONObjectHandle baseObj) {
if (baseObj == null) {
return null;
}

final TestJsonPropertyRenameType config = new TestJsonPropertyRenameType();
parse(baseObj, config);
return config;
}

public static void parse(final JSONObjectHandle baseObj,
final TestJsonPropertyRenameType config) {
if (baseObj == null || config == null) {
return;
}

// Parse assessmentAreaId
if (baseObj.has("id")) {
final int value = baseObj.getInteger("id");
config.setId(value);
}

// Parse name
if (baseObj.has("name") && !baseObj.isNull("name")) {
final String value = baseObj.getString("name");
config.setName(value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import nl.aerius.codegen.test.types.TestCustomParserType;
import nl.aerius.codegen.test.types.TestEnumListType;
import nl.aerius.codegen.test.types.TestEnumType;
import nl.aerius.codegen.test.types.TestJsonPropertyRenameType;
import nl.aerius.codegen.test.types.TestNestedMapType;
import nl.aerius.codegen.test.types.TestPrimitiveArrayType;
import nl.aerius.codegen.test.types.TestRecordType;
Expand Down Expand Up @@ -153,5 +154,11 @@ public static void parse(final JSONObjectHandle baseObj, final TestRootObjectTyp
final TestRecordType value = TestRecordTypeParser.parse(baseObj.getObject("recordType"));
config.setRecordType(value);
}

// Parse jsonPropertyRename
if (baseObj.has("jsonPropertyRename") && !baseObj.isNull("jsonPropertyRename")) {
final TestJsonPropertyRenameType value = TestJsonPropertyRenameTypeParser.parse(baseObj.getObject("jsonPropertyRename"));
config.setJsonPropertyRename(value);
}
}
}
Loading