Skip to content

Commit 9ff324d

Browse files
committed
support PropertyEncoder and PropertyDecoder
1 parent 4d432bd commit 9ff324d

25 files changed

Lines changed: 341 additions & 229 deletions

src/main/java/com/jsoniter/Codegen.java

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,14 @@ private synchronized static Decoder gen(String cacheKey, Type type) {
5252
return decoder;
5353
}
5454
}
55-
Type[] typeArgs = new Type[0];
56-
Class clazz;
57-
if (type instanceof ParameterizedType) {
58-
ParameterizedType pType = (ParameterizedType) type;
59-
clazz = (Class) pType.getRawType();
60-
typeArgs = pType.getActualTypeArguments();
61-
} else {
62-
clazz = (Class) type;
63-
}
64-
decoder = CodegenImplNative.NATIVE_DECODERS.get(clazz);
55+
ClassInfo classInfo = new ClassInfo(type);
56+
decoder = CodegenImplNative.NATIVE_DECODERS.get(classInfo.clazz);
6557
if (decoder != null) {
6658
return decoder;
6759
}
6860
addPlaceholderDecoderToSupportRecursiveStructure(cacheKey);
6961
if (mode == DecodingMode.REFLECTION_MODE) {
70-
decoder = ReflectionDecoderFactory.create(clazz, typeArgs);
62+
decoder = ReflectionDecoderFactory.create(classInfo);
7163
JsoniterSpi.addNewDecoder(cacheKey, decoder);
7264
return decoder;
7365
}
@@ -82,7 +74,7 @@ private synchronized static Decoder gen(String cacheKey, Type type) {
8274
}
8375
}
8476
}
85-
String source = genSource(clazz, typeArgs);
77+
String source = genSource(classInfo);
8678
source = "public static java.lang.Object decode_(com.jsoniter.JsonIterator iter) throws java.io.IOException { "
8779
+ source + "}";
8880
if ("true".equals(System.getenv("JSONITER_DEBUG"))) {
@@ -99,7 +91,7 @@ private synchronized static Decoder gen(String cacheKey, Type type) {
9991
JsoniterSpi.addNewDecoder(cacheKey, decoder);
10092
return decoder;
10193
} catch (Exception e) {
102-
String msg = "failed to generate decoder for: " + type + " with " + Arrays.toString(typeArgs) + ", exception: " + e;
94+
String msg = "failed to generate decoder for: " + classInfo + " with " + Arrays.toString(classInfo.typeArgs) + ", exception: " + e;
10395
msg = msg + "\n" + source;
10496
throw new JsonException(msg, e);
10597
}
@@ -218,24 +210,24 @@ private static void createDir(String cacheKey) {
218210
}
219211
}
220212

221-
private static String genSource(Class clazz, Type[] typeArgs) {
222-
if (clazz.isArray()) {
223-
return CodegenImplArray.genArray(clazz);
213+
private static String genSource(ClassInfo classInfo) {
214+
if (classInfo.clazz.isArray()) {
215+
return CodegenImplArray.genArray(classInfo);
224216
}
225-
if (Map.class.isAssignableFrom(clazz)) {
226-
return CodegenImplMap.genMap(clazz, typeArgs);
217+
if (Map.class.isAssignableFrom(classInfo.clazz)) {
218+
return CodegenImplMap.genMap(classInfo);
227219
}
228-
if (Collection.class.isAssignableFrom(clazz)) {
229-
return CodegenImplArray.genCollection(clazz, typeArgs);
220+
if (Collection.class.isAssignableFrom(classInfo.clazz)) {
221+
return CodegenImplArray.genCollection(classInfo);
230222
}
231-
if (clazz.isEnum()) {
232-
return CodegenImplEnum.genEnum(clazz);
223+
if (classInfo.clazz.isEnum()) {
224+
return CodegenImplEnum.genEnum(classInfo);
233225
}
234-
ClassDescriptor desc = ClassDescriptor.getDecodingClassDescriptor(clazz, false);
226+
ClassDescriptor desc = ClassDescriptor.getDecodingClassDescriptor(classInfo, false);
235227
if (shouldUseStrictMode(desc)) {
236-
return CodegenImplObjectStrict.genObjectUsingStrict(clazz, desc);
228+
return CodegenImplObjectStrict.genObjectUsingStrict(desc);
237229
} else {
238-
return CodegenImplObjectHash.genObjectUsingHash(clazz, desc);
230+
return CodegenImplObjectHash.genObjectUsingHash(desc);
239231
}
240232
}
241233

src/main/java/com/jsoniter/CodegenImplArray.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.jsoniter;
22

3+
import com.jsoniter.spi.ClassInfo;
4+
35
import java.lang.reflect.Type;
46
import java.util.*;
57

@@ -11,10 +13,10 @@ class CodegenImplArray {
1113
add(Vector.class);
1214
}};
1315

14-
public static String genArray(Class clazz) {
15-
Class compType = clazz.getComponentType();
16+
public static String genArray(ClassInfo classInfo) {
17+
Class compType = classInfo.clazz.getComponentType();
1618
if (compType.isArray()) {
17-
throw new IllegalArgumentException("nested array not supported: " + clazz.getCanonicalName());
19+
throw new IllegalArgumentException("nested array not supported: " + classInfo.clazz.getCanonicalName());
1820
}
1921
StringBuilder lines = new StringBuilder();
2022
append(lines, "com.jsoniter.CodegenAccess.resetExistingObject(iter);");
@@ -77,11 +79,11 @@ public static String genArray(Class clazz) {
7779
"{{op}}", CodegenImplNative.genReadOp(compType));
7880
}
7981

80-
public static String genCollection(Class clazz, Type[] typeArgs) {
81-
if (WITH_CAPACITY_COLLECTION_CLASSES.contains(clazz)) {
82-
return CodegenImplArray.genCollectionWithCapacity(clazz, typeArgs[0]);
82+
public static String genCollection(ClassInfo classInfo) {
83+
if (WITH_CAPACITY_COLLECTION_CLASSES.contains(classInfo.clazz)) {
84+
return CodegenImplArray.genCollectionWithCapacity(classInfo.clazz, classInfo.typeArgs[0]);
8385
} else {
84-
return CodegenImplArray.genCollectionWithoutCapacity(clazz, typeArgs[0]);
86+
return CodegenImplArray.genCollectionWithoutCapacity(classInfo.clazz, classInfo.typeArgs[0]);
8587
}
8688
}
8789

src/main/java/com/jsoniter/CodegenImplEnum.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package com.jsoniter;
22

3+
import com.jsoniter.spi.ClassInfo;
4+
35
import java.util.*;
46

57
class CodegenImplEnum {
6-
public static String genEnum(Class clazz) {
8+
public static String genEnum(ClassInfo classInfo) {
79
StringBuilder lines = new StringBuilder();
810
append(lines, "if (iter.readNull()) { return null; }");
911
append(lines, "com.jsoniter.spi.Slice field = com.jsoniter.CodegenAccess.readSlice(iter);");
1012
append(lines, "switch (field.len()) {");
11-
append(lines, renderTriTree(buildTriTree(Arrays.asList(clazz.getEnumConstants()))));
13+
append(lines, renderTriTree(buildTriTree(Arrays.asList(classInfo.clazz.getEnumConstants()))));
1214
append(lines, "}"); // end of switch
13-
append(lines, String.format("throw iter.reportError(\"decode enum\", field + \" is not valid enum for %s\");", clazz.getName()));
15+
append(lines, String.format("throw iter.reportError(\"decode enum\", field + \" is not valid enum for %s\");", classInfo.clazz.getName()));
1416
return lines.toString();
1517
}
1618

src/main/java/com/jsoniter/CodegenImplMap.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package com.jsoniter;
22

3+
import com.jsoniter.spi.ClassInfo;
34
import com.jsoniter.spi.TypeLiteral;
45

56
import java.lang.reflect.Type;
6-
import java.util.HashMap;
7-
import java.util.Map;
87

98
class CodegenImplMap {
109

11-
public static String genMap(Class clazz, Type[] typeArgs) {
12-
Type keyType = typeArgs[0];
13-
Type valueType = typeArgs[1];
10+
public static String genMap(ClassInfo classInfo) {
11+
Type keyType = classInfo.typeArgs[0];
12+
Type valueType = classInfo.typeArgs[1];
1413
StringBuilder lines = new StringBuilder();
1514
append(lines, "{{clazz}} map = ({{clazz}})com.jsoniter.CodegenAccess.resetExistingObject(iter);");
1615
append(lines, "if (iter.readNull()) { return null; }");
@@ -29,7 +28,7 @@ public static String genMap(Class clazz, Type[] typeArgs) {
2928
append(lines, "} while (com.jsoniter.CodegenAccess.nextToken(iter) == ',');");
3029
append(lines, "return map;");
3130
return lines.toString()
32-
.replace("{{clazz}}", clazz.getName())
31+
.replace("{{clazz}}", classInfo.clazz.getName())
3332
.replace("{{op}}", CodegenImplNative.genReadOp(valueType));
3433
}
3534

src/main/java/com/jsoniter/CodegenImplObjectHash.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
class CodegenImplObjectHash {
88

99
// the implementation is from dsljson, it is the fastest although has the risk not matching field strictly
10-
public static String genObjectUsingHash(Class clazz, ClassDescriptor desc) {
10+
public static String genObjectUsingHash(ClassDescriptor desc) {
11+
Class clazz = desc.clazz;
1112
StringBuilder lines = new StringBuilder();
1213
// === if null, return null
1314
append(lines, "java.lang.Object existingObj = com.jsoniter.CodegenAccess.resetExistingObject(iter);");
@@ -77,11 +78,11 @@ public int compare(String o1, String o2) {
7778
int intHash = calcHash(fromName);
7879
if (intHash == 0) {
7980
// hash collision, 0 can not be used as sentinel
80-
return CodegenImplObjectStrict.genObjectUsingStrict(clazz, desc);
81+
return CodegenImplObjectStrict.genObjectUsingStrict(desc);
8182
}
8283
if (knownHashes.contains(intHash)) {
8384
// hash collision with other field can not be used as sentinel
84-
return CodegenImplObjectStrict.genObjectUsingStrict(clazz, desc);
85+
return CodegenImplObjectStrict.genObjectUsingStrict(desc);
8586
}
8687
knownHashes.add(intHash);
8788
append(lines, "case " + intHash + ": ");

src/main/java/com/jsoniter/CodegenImplObjectStrict.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class CodegenImplObjectStrict {
2121
put("long", "0");
2222
}};
2323

24-
public static String genObjectUsingStrict(Class clazz, ClassDescriptor desc) {
24+
public static String genObjectUsingStrict(ClassDescriptor desc) {
2525
List<Binding> allBindings = desc.allDecoderBindings();
2626
int lastRequiredIdx = assignMaskForRequiredProperties(allBindings);
2727
boolean hasRequiredBinding = lastRequiredIdx > 0;
@@ -126,7 +126,7 @@ public static String genObjectUsingStrict(Class clazz, ClassDescriptor desc) {
126126
appendSetExtraToKeyValueTypeWrappers(lines, desc);
127127
}
128128
if (!desc.ctor.parameters.isEmpty()) {
129-
append(lines, String.format("%s obj = {{newInst}};", CodegenImplNative.getTypeName(clazz)));
129+
append(lines, String.format("%s obj = {{newInst}};", CodegenImplNative.getTypeName(desc.clazz)));
130130
for (Binding field : desc.fields) {
131131
append(lines, String.format("obj.%s = _%s_;", field.field.getName(), field.name));
132132
}
@@ -137,8 +137,8 @@ public static String genObjectUsingStrict(Class clazz, ClassDescriptor desc) {
137137
appendWrappers(desc.bindingTypeWrappers, lines);
138138
append(lines, "return obj;");
139139
return lines.toString()
140-
.replace("{{clazz}}", clazz.getCanonicalName())
141-
.replace("{{newInst}}", CodegenImplObjectHash.genNewInstCode(clazz, desc.ctor));
140+
.replace("{{clazz}}", desc.clazz.getCanonicalName())
141+
.replace("{{newInst}}", CodegenImplObjectHash.genNewInstCode(desc.clazz, desc.ctor));
142142
}
143143

144144
private static void appendSetExtraToKeyValueTypeWrappers(StringBuilder lines, ClassDescriptor desc) {

src/main/java/com/jsoniter/ReflectionDecoderFactory.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package com.jsoniter;
22

3+
import com.jsoniter.spi.ClassInfo;
34
import com.jsoniter.spi.Decoder;
45

56
import java.lang.reflect.Type;
67
import java.util.Collection;
78
import java.util.Map;
89

910
class ReflectionDecoderFactory {
10-
public static Decoder create(Class clazz, Type... typeArgs) {
11+
public static Decoder create(ClassInfo classAndArgs) {
12+
Class clazz = classAndArgs.clazz;
13+
Type[] typeArgs = classAndArgs.typeArgs;
1114
if (clazz.isArray()) {
1215
return new ReflectionArrayDecoder(clazz);
1316
}
@@ -20,6 +23,6 @@ public static Decoder create(Class clazz, Type... typeArgs) {
2023
if (clazz.isEnum()) {
2124
return new ReflectionEnumDecoder(clazz);
2225
}
23-
return new ReflectionObjectDecoder(clazz).create();
26+
return new ReflectionObjectDecoder(classAndArgs).create();
2427
}
2528
}

src/main/java/com/jsoniter/ReflectionObjectDecoder.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,33 @@ public String toString() {
2424
private int tempIdx;
2525
private ClassDescriptor desc;
2626

27-
public ReflectionObjectDecoder(Class clazz) {
27+
public ReflectionObjectDecoder(ClassInfo classInfo) {
2828
try {
29-
init(clazz);
29+
init(classInfo);
3030
} catch (Exception e) {
3131
throw new JsonException(e);
3232
}
3333
}
3434

35-
private final void init(Class clazz) throws Exception {
36-
ClassDescriptor desc = ClassDescriptor.getDecodingClassDescriptor(clazz, true);
35+
private final void init(ClassInfo classInfo) throws Exception {
36+
Class clazz = classInfo.clazz;
37+
ClassDescriptor desc = ClassDescriptor.getDecodingClassDescriptor(classInfo, true);
3738
for (Binding param : desc.ctor.parameters) {
38-
addBinding(clazz, param);
39+
addBinding(classInfo, param);
3940
}
4041
this.desc = desc;
4142
if (desc.ctor.objectFactory == null && desc.ctor.ctor == null && desc.ctor.staticFactory == null) {
4243
throw new JsonException("no constructor for: " + desc.clazz);
4344
}
4445
for (Binding field : desc.fields) {
45-
addBinding(clazz, field);
46+
addBinding(classInfo, field);
4647
}
4748
for (Binding setter : desc.setters) {
48-
addBinding(clazz, setter);
49+
addBinding(classInfo, setter);
4950
}
5051
for (WrapperDescriptor setter : desc.bindingTypeWrappers) {
5152
for (Binding param : setter.parameters) {
52-
addBinding(clazz, param);
53+
addBinding(classInfo, param);
5354
}
5455
}
5556
if (requiredIdx > 63) {
@@ -63,7 +64,7 @@ private final void init(Class clazz) throws Exception {
6364
}
6465
}
6566

66-
private void addBinding(Class clazz, final Binding binding) {
67+
private void addBinding(ClassInfo classInfo, final Binding binding) {
6768
if (binding.asMissingWhenNotPresent) {
6869
binding.mask = 1L << requiredIdx;
6970
requiredIdx++;
@@ -87,7 +88,7 @@ public Object decode(JsonIterator iter) throws IOException {
8788
for (String fromName : binding.fromNames) {
8889
Slice slice = Slice.make(fromName);
8990
if (allBindings.containsKey(slice)) {
90-
throw new JsonException("name conflict found in " + clazz + ": " + fromName);
91+
throw new JsonException("name conflict found in " + classInfo.clazz + ": " + fromName);
9192
}
9293
allBindings.put(slice, binding);
9394
}

src/main/java/com/jsoniter/annotation/JsoniterConfig.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,15 @@ public void updateClassDescriptor(ClassDescriptor desc) {
6262
desc.asExtraForUnknownProperties = true;
6363
}
6464
for (String fieldName : jsonObject.unknownPropertiesWhitelist()) {
65-
Binding binding = new Binding(desc.clazz, desc.lookup, Object.class);
65+
Binding binding = new Binding(desc.classInfo, desc.lookup, Object.class);
6666
binding.name = fieldName;
6767
binding.fromNames = new String[]{binding.name};
6868
binding.toNames = new String[0];
6969
binding.shouldSkip = true;
7070
desc.fields.add(binding);
7171
}
7272
for (String fieldName : jsonObject.unknownPropertiesBlacklist()) {
73-
Binding binding = new Binding(desc.clazz, desc.lookup, Object.class);
73+
Binding binding = new Binding(desc.classInfo, desc.lookup, Object.class);
7474
binding.name = fieldName;
7575
binding.fromNames = new String[]{binding.name};
7676
binding.toNames = new String[0];
@@ -119,7 +119,7 @@ private void detectWrappers(ClassDescriptor desc, List<Method> allMethods) {
119119
wrapper.method = method;
120120
for (int i = 0; i < annotations.length; i++) {
121121
Annotation[] paramAnnotations = annotations[i];
122-
Binding binding = new Binding(desc.clazz, desc.lookup, method.getGenericParameterTypes()[i]);
122+
Binding binding = new Binding(desc.classInfo, desc.lookup, method.getGenericParameterTypes()[i]);
123123
JsonProperty jsonProperty = getJsonProperty(paramAnnotations);
124124
if (jsonProperty != null) {
125125
updateBindingWithJsonProperty(binding, jsonProperty);
@@ -175,7 +175,7 @@ private void detectStaticFactory(ClassDescriptor desc, List<Method> allMethods)
175175
for (int i = 0; i < annotations.length; i++) {
176176
Annotation[] paramAnnotations = annotations[i];
177177
JsonProperty jsonProperty = getJsonProperty(paramAnnotations);
178-
Binding binding = new Binding(desc.clazz, desc.lookup, method.getGenericParameterTypes()[i]);
178+
Binding binding = new Binding(desc.classInfo, desc.lookup, method.getGenericParameterTypes()[i]);
179179
if (jsonProperty != null) {
180180
updateBindingWithJsonProperty(binding, jsonProperty);
181181
}
@@ -204,7 +204,7 @@ private void detectCtor(ClassDescriptor desc) {
204204
for (int i = 0; i < annotations.length; i++) {
205205
Annotation[] paramAnnotations = annotations[i];
206206
JsonProperty jsonProperty = getJsonProperty(paramAnnotations);
207-
Binding binding = new Binding(desc.clazz, desc.lookup, ctor.getGenericParameterTypes()[i]);
207+
Binding binding = new Binding(desc.classInfo, desc.lookup, ctor.getGenericParameterTypes()[i]);
208208
if (jsonProperty != null) {
209209
updateBindingWithJsonProperty(binding, jsonProperty);
210210
}

0 commit comments

Comments
 (0)