Skip to content

Commit

Permalink
github.com//issues/64
Browse files Browse the repository at this point in the history
github.com//issues/65
github.com//issues/67
  • Loading branch information
miho committed Aug 5, 2024
1 parent f617fe0 commit 3eb44d1
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ private T deserializeNode(JsonParser p, DeserializationContext ctxt, JsonNode no
// iterate over node fields and look for "@vmf-type" field to determine the actual type
// do so and allow reiteration over the fields

actualClass = getaVMFTypeClass(p, node, actualClass);
actualClass = getVMFTypeClass(p, node, actualClass);

try {

Expand All @@ -308,7 +308,8 @@ private T deserializeNode(JsonParser p, DeserializationContext ctxt, JsonNode no
Map<String, Method> methodMap = new HashMap<>();
for (Method method : methods) {
if (method.getName().startsWith("with")) {
String fieldName = method.getName().substring(4).toLowerCase();

String fieldName = getFieldNameFromMethod(actualClass, method);

try {

Expand Down Expand Up @@ -342,7 +343,8 @@ private T deserializeNode(JsonParser p, DeserializationContext ctxt, JsonNode no

// Iterate over JSON fields and invoke corresponding builder methods
node.fields().forEachRemaining(entry -> {
String fieldName = entry.getKey().toLowerCase();
String fieldName = entry.getKey();

JsonNode value = entry.getValue();

// check if we have a method for the field
Expand Down Expand Up @@ -374,7 +376,7 @@ private T deserializeNode(JsonParser p, DeserializationContext ctxt, JsonNode no
? deserializeField(ctxt, e, elementTypeClass)
: ctxt.readValue(
e.traverse(ctxt.getParser().getCodec()),
getaVMFTypeClass(ctxt.getParser(), e, elementTypeClass));
getVMFTypeClass(ctxt.getParser(), e, elementTypeClass));

// Add the element to the collection
collection.add(elementValue);
Expand All @@ -388,7 +390,7 @@ private T deserializeNode(JsonParser p, DeserializationContext ctxt, JsonNode no
? deserializeField(ctxt, element, elementTypeClass)
: ctxt.readValue(
element.traverse(ctxt.getParser().getCodec()),
getaVMFTypeClass(ctxt.getParser(), element, elementTypeClass));
getVMFTypeClass(ctxt.getParser(), element, elementTypeClass));

// Add the element to the collection
collection.add(elementValue);
Expand Down Expand Up @@ -416,6 +418,39 @@ private T deserializeNode(JsonParser p, DeserializationContext ctxt, JsonNode no
}
}

private String getFieldNameFromMethod(Class<?> actualClass, Method method) {
String fieldName = method.getName().substring(4,5).toLowerCase()
+ method.getName().substring(5);

if(isVMFObj(actualClass)) {
try {
Class<?> builderClass = getBuilderClass(actualClass);
Object builder = builderClass.getDeclaredMethod("newInstance").invoke(null);

// Build the final object
Method buildMethod = builderClass.getDeclaredMethod("build");
var obj = (VObject) buildMethod.invoke(builder);

var prop = obj.vmf().reflect().propertyByName(fieldName).get();

var a = prop.annotationByKey("vmf:jackson:rename");
if(a.isPresent()) {
fieldName = a.get().getValue();
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}

return fieldName;
}

private static Object deserializeField(DeserializationContext ctxt, JsonNode value, Class<?> paramType) throws IllegalAccessException, InvocationTargetException, IOException {
// Handle null values
if (value.isNull()) {
Expand Down Expand Up @@ -449,7 +484,7 @@ private static Object deserializeField(DeserializationContext ctxt, JsonNode val
}
}

private Class<?> getaVMFTypeClass(JsonParser p, JsonNode node, Class<?> actualClass) {
private Class<?> getVMFTypeClass(JsonParser p, JsonNode node, Class<?> actualClass) {
String vmfTypeFieldName = "@vmf-type";

var clsName = "com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser";
Expand Down Expand Up @@ -642,7 +677,7 @@ public void serialize(T value, JsonGenerator gen, SerializerProvider provider) t
isParentOfPropContainer(p)
|| !p.getType().isModelType()
|| propValue instanceof eu.mihosoft.vmf.runtime.core.Immutable)) {
gen.writeFieldName(p.getName());
gen.writeFieldName(getFieldNameForProperty(p));
gen.writeObject(propValue);
}
} catch (IOException e) {
Expand All @@ -655,6 +690,21 @@ public void serialize(T value, JsonGenerator gen, SerializerProvider provider) t
}
}

/**
* Get the field name for a property. This method is used to determine the field name of a property. It checks for
* the presence of the `@vmf:jackson:rename` annotation and uses the value of the annotation as the field name if
* present.
* @param p the property to get the field name for
* @return the field name of the property
*/
private static String getFieldNameForProperty(Property p) {
var a = p.annotationByKey("vmf:jackson:rename");
if(a.isPresent()) {
return a.get().getValue();
}
return p.getName();
}

/**
* Checks if the type is extended by another model type. Interface-only types are not considered.
* @param model the model object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ void testModel() throws JsonProcessingException {

ExternalTypeModel01 model = ExternalTypeModel01.newBuilder()
.withName("Model 01")
.withNameValue("Model 01 Value")
.withEnumValue(ExternalEnum.SECOND)
.withTags(new String[]{"tag1", "tag2", "tag3"})
.withValues(new Integer[]{1, 2, 3})
Expand All @@ -38,6 +39,8 @@ void testModel() throws JsonProcessingException {
String json2 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(model2);
System.out.println(json2);

assertEquals(json, json2);

// check if deserialization worked
assertTrue(model.vmf().content().equals(model2));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ void testModel() {
e.printStackTrace();
}

// check if models are equal
assertTrue(model.vmf().content().equals(model2) , "Models must be equal");

// output second model as json and compare to original model json
try {
var json2 = writer.writeValueAsString(model2);
Expand All @@ -96,6 +93,9 @@ void testModel() {
e.printStackTrace();
}

// check if models are equal
assertTrue(model.vmf().content().equals(model2) , "Models must be equal");

// output the model as xml
var xmlMapper = new XmlMapper();
xmlMapper.registerModule(VMFJacksonModule.newInstance(VMFJacksonModule.RUNTIME_TYPE.EXPERIMENTAL)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package eu.mihosoft.vmf.jackson.test.renameprops01;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.mihosoft.vmf.jackson.VMFJacksonModule;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class RenamePropsModelTest {

@org.junit.jupiter.api.Test
void testModel() throws JsonProcessingException {

RenamePropsModel model = RenamePropsModel.newBuilder()
.withCOMPort("COM1")
.build();

var mapper = new ObjectMapper();
mapper.registerModule(VMFJacksonModule.newInstance(VMFJacksonModule.RUNTIME_TYPE.EXPERIMENTAL)
.withTypeAlias("rename-props-model", RenamePropsModel.class.getName())
);


String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(model);
System.out.println(json);

// deserialize
RenamePropsModel model2 = mapper.readValue(json, RenamePropsModel.class);

// serialize again
String json2 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(model2);
System.out.println(json2);

assertEquals(json, json2);

// check if deserialization worked
assertTrue(model.vmf().content().equals(model2));


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ interface ExternalTypeModel01 {

String getName();

String getnameValue();

ExternalEnum getEnumValue();

String[] getTags();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package eu.mihosoft.vmf.jackson.test.renameprops01.vmfmodel;

import eu.mihosoft.vmf.core.Annotation;

interface RenamePropsModel {

// We want to prevent the property from being called "cOMPort" in the generated JSON
@Annotation(key = "vmf:jackson:rename", value = "comPort")
String getCOMPort();

}

0 comments on commit 3eb44d1

Please sign in to comment.