Skip to content

Commit d9370dd

Browse files
Refactor JsonViewDescriptorDeserializer and JsonViewDescriptorSerializer for improved JSON processing and collection handling
1 parent ac6c25c commit d9370dd

2 files changed

Lines changed: 198 additions & 170 deletions

File tree

platform/core/viewers/src/main/java/tools/dynamia/viewers/JsonViewDescriptorDeserializer.java

Lines changed: 88 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package tools.dynamia.viewers;
1919

2020

21+
import com.fasterxml.jackson.annotation.JsonIgnore;
2122
import tools.dynamia.commons.ObjectOperations;
2223
import tools.dynamia.commons.logger.LoggingService;
2324
import tools.dynamia.commons.logger.SLF4JLoggingService;
@@ -29,109 +30,130 @@
2930
import tools.jackson.databind.DeserializationContext;
3031
import tools.jackson.databind.JsonNode;
3132
import tools.jackson.databind.deser.std.StdDeserializer;
32-
import tools.jackson.databind.util.StdDateFormat;
3333

3434
import java.math.BigDecimal;
3535
import java.util.*;
36+
import java.util.concurrent.ConcurrentHashMap;
37+
import java.util.function.Function;
3638

3739
public class JsonViewDescriptorDeserializer extends StdDeserializer<Object> {
3840

3941
private final ViewDescriptor viewDescriptor;
40-
private final StdDateFormat dateFormat = new StdDateFormat();
4142
private static final LoggingService LOGGER = new SLF4JLoggingService(JsonViewDescriptorDeserializer.class);
4243

43-
public JsonViewDescriptorDeserializer(ViewDescriptor viewDescriptor) {
44-
this(viewDescriptor, null);
44+
private static final Map<Class<?>, Function<JsonNode, Object>> TYPE_EXTRACTORS = new HashMap<>();
45+
private static final Map<Class<?>, ViewDescriptor> DESCRIPTOR_CACHE = new ConcurrentHashMap<>();
46+
47+
static {
48+
TYPE_EXTRACTORS.put(String.class, JsonNode::stringValue);
49+
TYPE_EXTRACTORS.put(Long.class, JsonNode::longValue);
50+
TYPE_EXTRACTORS.put(long.class, JsonNode::longValue);
51+
TYPE_EXTRACTORS.put(Integer.class, JsonNode::intValue);
52+
TYPE_EXTRACTORS.put(int.class, JsonNode::intValue);
53+
TYPE_EXTRACTORS.put(Float.class, JsonNode::floatValue);
54+
TYPE_EXTRACTORS.put(float.class, JsonNode::floatValue);
55+
TYPE_EXTRACTORS.put(Double.class, JsonNode::doubleValue);
56+
TYPE_EXTRACTORS.put(double.class, JsonNode::doubleValue);
57+
TYPE_EXTRACTORS.put(BigDecimal.class, JsonNode::decimalValue);
58+
TYPE_EXTRACTORS.put(Boolean.class, JsonNode::asBoolean);
59+
TYPE_EXTRACTORS.put(boolean.class, JsonNode::asBoolean);
60+
}
4561

62+
public JsonViewDescriptorDeserializer(ViewDescriptor viewDescriptor) {
63+
this(viewDescriptor, Object.class);
4664
}
4765

4866
public JsonViewDescriptorDeserializer(ViewDescriptor viewDescriptor, Class<Object> t) {
4967
super(t);
5068
this.viewDescriptor = viewDescriptor;
5169
}
5270

53-
5471
@Override
5572
public Object deserialize(JsonParser jp, DeserializationContext ctxt) {
56-
5773
JsonNode node = jp.readValueAsTree();
5874
return parseNode(viewDescriptor.getBeanClass(), node, viewDescriptor);
59-
6075
}
6176

62-
private Object parseNode(Class type, JsonNode node, ViewDescriptor viewDescriptor) {
63-
@SuppressWarnings("unchecked") Object object = ObjectOperations.newInstance(type);
64-
for (Field field : Viewers.getFields(viewDescriptor)) {
77+
private Object parseNode(Class<?> type, JsonNode node, ViewDescriptor descriptor) {
78+
Object object = ObjectOperations.newInstance(type);
79+
for (Field field : Viewers.getFields(descriptor)) {
6580
PropertyInfo fieldInfo = field.getPropertyInfo();
66-
String fieldName = field.getName();
67-
JsonNode fieldNode = node.get(fieldName);
81+
if (fieldInfo.isAnnotationPresent(JsonIgnore.class)) {
82+
continue;
83+
}
84+
85+
JsonNode fieldNode = node.get(field.getName());
6886
if (fieldNode == null) {
6987
continue;
7088
}
7189

7290
if (fieldInfo.isCollection()) {
73-
Collection collection = (Collection) ObjectOperations.invokeGetMethod(object, fieldInfo);
74-
if (collection == null) {
75-
if (fieldInfo.getType() == List.class) {
76-
collection = new ArrayList();
77-
} else if (fieldInfo.getType() == Set.class) {
78-
collection = new HashSet();
79-
} else {
80-
collection = (Collection) ObjectOperations.newInstance(fieldInfo.getType());
81-
}
82-
ObjectOperations.setFieldValue(fieldInfo, object, collection);
83-
}
84-
85-
ViewDescriptor collectionDescriptor = Viewers.findViewDescriptor(fieldInfo.getGenericType(), "json-form");
86-
if (collectionDescriptor == null) {
87-
collectionDescriptor = Viewers.getViewDescriptor(fieldInfo.getGenericType(), "form");
88-
}
89-
String parentName = ObjectOperations.findParentPropertyName(type, fieldInfo.getGenericType());
90-
if (field.getParams().get("parentName") != null) {
91-
parentName = field.getParams().get("parentName").toString();
92-
}
93-
for (JsonNode child : fieldNode) {
94-
Object item = parseNode(fieldInfo.getGenericType(), child, collectionDescriptor);
95-
ObjectOperations.invokeSetMethod(item, parentName, object);
96-
//noinspection unchecked
97-
collection.add(item);
98-
}
99-
91+
processCollectionField(object, field, fieldInfo, fieldNode, type);
10092
} else {
101-
Object fieldValue = getNodeValue(fieldInfo, fieldNode);
102-
try {
103-
ObjectOperations.invokeSetMethod(object, fieldName, fieldValue);
104-
} catch (ReflectionException e) {
105-
LOGGER.warn("Cannot parse json to field " + fieldName + " = " + fieldValue + ": " + e.getMessage());
106-
}
107-
108-
93+
setSimpleField(object, field.getName(), fieldInfo, fieldNode);
10994
}
11095
}
11196
return object;
11297
}
11398

114-
public static Object getNodeValue(PropertyInfo fieldInfo, JsonNode fieldNode) {
115-
Object fieldValue = null;
99+
private void processCollectionField(Object object, Field field, PropertyInfo fieldInfo,
100+
JsonNode fieldNode, Class<?> parentType) {
101+
Collection<Object> collection = getOrCreateCollection(object, fieldInfo);
102+
ViewDescriptor collectionDescriptor = resolveCollectionDescriptor(fieldInfo.getGenericType());
103+
String parentName = resolveParentName(field, fieldInfo, parentType);
116104

105+
for (JsonNode child : fieldNode) {
106+
Object item = parseNode(fieldInfo.getGenericType(), child, collectionDescriptor);
107+
ObjectOperations.invokeSetMethod(item, parentName, object);
108+
collection.add(item);
109+
}
110+
}
111+
112+
@SuppressWarnings("unchecked")
113+
private Collection<Object> getOrCreateCollection(Object object, PropertyInfo fieldInfo) {
114+
Collection<Object> collection = (Collection<Object>) ObjectOperations.invokeGetMethod(object, fieldInfo);
115+
if (collection == null) {
116+
collection = createEmptyCollection(fieldInfo.getType());
117+
ObjectOperations.setFieldValue(fieldInfo, object, collection);
118+
}
119+
return collection;
120+
}
121+
122+
@SuppressWarnings("unchecked")
123+
private Collection<Object> createEmptyCollection(Class<?> type) {
124+
if (type == List.class) return new ArrayList<>();
125+
if (type == Set.class) return new HashSet<>();
126+
return (Collection<Object>) ObjectOperations.newInstance(type);
127+
}
128+
129+
private String resolveParentName(Field field, PropertyInfo fieldInfo, Class<?> parentType) {
130+
Object customParent = field.getParams().get("parentName");
131+
return customParent != null
132+
? customParent.toString()
133+
: ObjectOperations.findParentPropertyName(parentType, fieldInfo.getGenericType());
134+
}
135+
136+
private void setSimpleField(Object object, String fieldName, PropertyInfo fieldInfo, JsonNode fieldNode) {
137+
Object fieldValue = getNodeValue(fieldInfo, fieldNode);
138+
try {
139+
ObjectOperations.invokeSetMethod(object, fieldName, fieldValue);
140+
} catch (ReflectionException e) {
141+
LOGGER.warn("Cannot parse json to field " + fieldName + " = " + fieldValue + ": " + e.getMessage());
142+
}
143+
}
144+
145+
private ViewDescriptor resolveCollectionDescriptor(Class<?> genericType) {
146+
return DESCRIPTOR_CACHE.computeIfAbsent(genericType, type -> {
147+
ViewDescriptor descriptor = Viewers.findViewDescriptor(type, "json-form");
148+
return descriptor != null ? descriptor : Viewers.getViewDescriptor(type, "form");
149+
});
150+
}
151+
152+
public static Object getNodeValue(PropertyInfo fieldInfo, JsonNode fieldNode) {
117153
if (DomainUtils.isEntity(fieldInfo.getType()) && fieldNode.get("id") != null) {
118-
long id = fieldNode.get("id").asLong();
119-
fieldValue = DomainUtils.lookupCrudService().find(fieldInfo.getType(), id);
120-
} else if (fieldInfo.is(String.class)) {
121-
fieldValue = fieldNode.textValue();
122-
} else if (fieldInfo.is(Long.class) || fieldInfo.is(long.class)) {
123-
fieldValue = fieldNode.longValue();
124-
} else if (fieldInfo.is(Integer.class) || fieldInfo.is(int.class)) {
125-
fieldValue = fieldNode.intValue();
126-
} else if (fieldInfo.is(Float.class) || fieldInfo.is(float.class)) {
127-
fieldValue = fieldNode.floatValue();
128-
} else if (fieldInfo.is(Double.class) || fieldInfo.is(double.class)) {
129-
fieldValue = fieldNode.doubleValue();
130-
} else if (fieldInfo.is(BigDecimal.class)) {
131-
fieldValue = fieldNode.decimalValue();
132-
} else if (fieldInfo.is(Boolean.class)) {
133-
fieldValue = fieldNode.booleanValue();
154+
return DomainUtils.lookupCrudService().find(fieldInfo.getType(), fieldNode.get("id").asLong());
134155
}
135-
return fieldValue;
156+
Function<JsonNode, Object> extractor = TYPE_EXTRACTORS.get(fieldInfo.getType());
157+
return extractor != null ? extractor.apply(fieldNode) : null;
136158
}
137159
}

0 commit comments

Comments
 (0)