Skip to content

Commit e34ad27

Browse files
committed
simplify extension
1 parent 0e5ea23 commit e34ad27

12 files changed

Lines changed: 156 additions & 102 deletions

src/main/java/com/jsoniter/Binding.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
import java.lang.reflect.Type;
55

66
public class Binding {
7+
// input
78
public Class clazz;
8-
public String[] fromNames;
99
public String name;
1010
public Type valueType;
1111
public Annotation[] annotations;
12+
// output
13+
public String[] fromNames;
14+
public Decoder decoder;
1215

1316
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
1417
if (annotations == null) {
@@ -21,4 +24,31 @@ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
2124
}
2225
return null;
2326
}
27+
28+
@Override
29+
public boolean equals(Object o) {
30+
if (this == o) return true;
31+
if (o == null || getClass() != o.getClass()) return false;
32+
33+
Binding binding = (Binding) o;
34+
35+
if (clazz != null ? !clazz.equals(binding.clazz) : binding.clazz != null) return false;
36+
return name != null ? name.equals(binding.name) : binding.name == null;
37+
}
38+
39+
@Override
40+
public int hashCode() {
41+
int result = clazz != null ? clazz.hashCode() : 0;
42+
result = 31 * result + (name != null ? name.hashCode() : 0);
43+
return result;
44+
}
45+
46+
@Override
47+
public String toString() {
48+
return "Binding{" +
49+
"clazz=" + clazz +
50+
", name='" + name + '\'' +
51+
", valueType=" + valueType +
52+
'}';
53+
}
2454
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,27 @@ public static void enableStrictMode() {
1717
strictMode = true;
1818
}
1919

20-
static Decoder getDecoder(String cacheKey, Type type, Type... typeArgs) {
20+
static Decoder getDecoder(String cacheKey, Type type) {
2121
Decoder decoder = cache.get(cacheKey);
2222
if (decoder != null) {
2323
return decoder;
2424
}
25-
return gen(cacheKey, type, typeArgs);
25+
return gen(cacheKey, type);
2626
}
2727

28-
private synchronized static Decoder gen(String cacheKey, Type type, Type[] typeArgs) {
28+
private synchronized static Decoder gen(String cacheKey, Type type) {
2929
Decoder decoder = cache.get(cacheKey);
3030
if (decoder != null) {
3131
return decoder;
3232
}
3333
for (Extension extension : ExtensionManager.extensions) {
34-
decoder = extension.createDecoder(type, typeArgs);
34+
decoder = extension.createDecoder(cacheKey, type);
3535
if (decoder != null) {
3636
addNewDecoder(cacheKey, decoder);
3737
return decoder;
3838
}
3939
}
40+
Type[] typeArgs = null;
4041
Class clazz;
4142
if (type instanceof ParameterizedType) {
4243
ParameterizedType pType = (ParameterizedType) type;

src/main/java/com/jsoniter/CodegenImplNative.java

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,13 @@ public static String genReadOp(Type type) {
8080
}
8181

8282
public static String genField(Binding field, String cacheKey) {
83-
Type fieldType = field.valueType;
8483
String fieldCacheKey = field.name + "@" + cacheKey;
85-
Decoder decoder = createFieldDecoder(fieldCacheKey, field);
84+
if (field.decoder != null) {
85+
Codegen.cache.put(fieldCacheKey, field.decoder);
86+
}
87+
// the field decoder might be registered directly
88+
Decoder decoder = Codegen.cache.get(fieldCacheKey);
89+
Type fieldType = field.valueType;
8690
if (decoder == null) {
8791
return String.format("(%s)%s", getTypeName(fieldType), CodegenImplNative.genReadOp(fieldType));
8892
}
@@ -139,21 +143,6 @@ public static String genField(Binding field, String cacheKey) {
139143
getTypeName(fieldType), fieldCacheKey);
140144
}
141145

142-
private static Decoder createFieldDecoder(String fieldCacheKey, Binding field) {
143-
// directly registered field decoder
144-
Decoder decoder = Codegen.cache.get(fieldCacheKey);
145-
if (decoder != null) {
146-
return decoder;
147-
}
148-
// provided by extension
149-
decoder = ExtensionManager.createFieldDecoder(fieldCacheKey, field);
150-
if (decoder != null) {
151-
Codegen.addNewDecoder(fieldCacheKey, decoder);
152-
return decoder;
153-
}
154-
return null;
155-
}
156-
157146
public static String getTypeName(Type fieldType) {
158147
if (fieldType instanceof Class) {
159148
Class clazz = (Class) fieldType;

src/main/java/com/jsoniter/EmptyExtension.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,13 @@
66
public class EmptyExtension implements Extension {
77

88
@Override
9-
public Decoder createDecoder(Type type, Type... typeArgs) {
9+
public Decoder createDecoder(String cacheKey, Type type) {
1010
return null;
1111
}
1212

1313
@Override
14-
public Decoder createDecoder(Binding field) {
15-
return null;
16-
}
17-
18-
@Override
19-
public String[] getBindFrom(Binding field) {
20-
return null;
14+
public boolean updateBinding(Binding field) {
15+
return false;
2116
}
2217

2318
@Override

src/main/java/com/jsoniter/Extension.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,25 @@ public interface Extension {
77
/**
88
* Customize type decoding
99
*
10-
* @param type change how to decode the type
11-
* @param typeArgs for generic type
12-
* @return null, if no special customization needed
13-
*/
14-
Decoder createDecoder(Type type, Type... typeArgs);
15-
16-
/**
17-
* Customize field of certain kind, for example having certain annotation
1810
*
19-
* @param field the field reflection object
11+
* @param cacheKey
12+
* @param type change how to decode the type
2013
* @return null, if no special customization needed
2114
*/
22-
Decoder createDecoder(Binding field);
15+
Decoder createDecoder(String cacheKey, Type type);
2316

2417
/**
25-
* Customize the binding source
18+
* Customize the binding source or decoder
2619
*
27-
* @param field the field reflection object
28-
* @return null, if fallback to default behavior. empty array to disable this binding
20+
* @param field binding information
21+
* @return true, if stops other extension from customizing same field
2922
*/
30-
String[] getBindFrom(Binding field);
23+
boolean updateBinding(Binding field);
3124

3225
/**
3326
* Customize which constructor to call
3427
*
35-
* @param clazz the instance class to create
28+
* @param clazz the class of instance to create
3629
* @return null, if fallback to default behavior
3730
*/
3831
CustomizedConstructor getConstructor(Class clazz);

src/main/java/com/jsoniter/ExtensionManager.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,6 @@ public static void registerExtension(Extension extension) {
1414
extensions.add(extension);
1515
}
1616

17-
public static Decoder createFieldDecoder(String fieldCacheKey, Binding field) {
18-
for (Extension extension : extensions) {
19-
Decoder decoder = extension.createDecoder(field);
20-
if (decoder != null) {
21-
return decoder;
22-
}
23-
}
24-
return null;
25-
}
26-
2717
public static CustomizedConstructor getCtor(Class clazz) {
2818
for (Extension extension : extensions) {
2919
CustomizedConstructor ctor = extension.getConstructor(clazz);
@@ -61,9 +51,7 @@ public static List<Binding> getFields(Class clazz) {
6151

6252
private static void updateFromNames(Binding binding) {
6353
for (Extension extension : extensions) {
64-
String[] fromNames = extension.getBindFrom(binding);
65-
if (fromNames != null) {
66-
binding.fromNames = fromNames;
54+
if (extension.updateBinding(binding)) {
6755
break;
6856
}
6957
}

src/main/java/com/jsoniter/TypeLiteral.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ protected TypeLiteral() {
2020

2121
}
2222

23+
private TypeLiteral(Type type, String cacheKey) {
24+
this.type = type;
25+
this.cacheKey = cacheKey;
26+
}
27+
2328
public static String generateCacheKey(Type type) {
2429
StringBuilder decoderClassName = new StringBuilder("codegen.");
2530
if (type instanceof Class) {
@@ -76,4 +81,16 @@ public Type getType() {
7681
public String getCacheKey() {
7782
return cacheKey;
7883
}
84+
85+
public static TypeLiteral create(Type type, String suffix) {
86+
return new TypeLiteral(type, generateCacheKey(type) + "." + suffix);
87+
}
88+
89+
@Override
90+
public String toString() {
91+
return "TypeLiteral{" +
92+
"type=" + type +
93+
", cacheKey='" + cacheKey + '\'' +
94+
'}';
95+
}
7996
}

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,21 @@ public static void enable() {
1616
}
1717

1818
@Override
19-
public String[] getBindFrom(Binding field) {
19+
public boolean updateBinding(Binding field) {
2020
JsonIgnore jsonIgnore = field.getAnnotation(JsonIgnore.class);
2121
if (jsonIgnore != null) {
22-
return new String[0];
22+
field.fromNames = new String[0];
23+
return true;
2324
}
2425
JsonProperty jsonProperty = field.getAnnotation(JsonProperty.class);
2526
if (jsonProperty != null) {
2627
String alternativeField = jsonProperty.value();
27-
if (alternativeField.equals(JsonProperty.USE_DEFAULT_NAME)) {
28-
alternativeField = field.name;
28+
if (!alternativeField.isEmpty()) {
29+
field.fromNames = new String[]{alternativeField};
30+
return true;
2931
}
30-
return new String[]{alternativeField};
3132
}
32-
return null;
33+
return false;
3334
}
3435

3536
@Override

src/test/java/com/jsoniter/TestAnnotation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ private StaticFactory() {
5454
}
5555

5656
@JsonCreator
57-
public static StaticFactory createObject(@JsonProperty("field1") int field1) {
57+
public static StaticFactory createObject(@JsonProperty(value = "field1") int field1) {
5858
StaticFactory obj = new StaticFactory();
5959
obj.field1 = field1;
6060
return obj;

src/test/java/com/jsoniter/TestCustomizeField.java

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -46,43 +46,19 @@ public int decodeInt(JsonIterator iter) throws IOException {
4646
assertEquals(100, myObject.field1);
4747
}
4848

49-
public static class TestObject3 {
50-
public int field1;
51-
}
52-
53-
public void test_customize_using_extension() throws IOException {
54-
JsonIterator.registerExtension(new EmptyExtension() {
55-
@Override
56-
public Decoder createDecoder(Binding field) {
57-
if (field.clazz == TestObject3.class && field.name.equals("field1")) {
58-
return new Decoder.IntDecoder() {
59-
60-
@Override
61-
public int decodeInt(JsonIterator iter) throws IOException {
62-
return Integer.valueOf(iter.readString());
63-
}
64-
};
65-
}
66-
return null;
67-
}
68-
});
69-
JsonIterator iter = JsonIterator.parse("{'field1': '100'}".replace('\'', '"'));
70-
TestObject3 myObject = iter.read(TestObject3.class);
71-
assertEquals(100, myObject.field1);
72-
}
73-
7449
public static class TestObject4 {
7550
public int field1;
7651
}
7752

7853
public void test_rename_field() throws IOException {
7954
JsonIterator.registerExtension(new EmptyExtension() {
8055
@Override
81-
public String[] getBindFrom(Binding field) {
56+
public boolean updateBinding(Binding field) {
8257
if (field.clazz == TestObject4.class && field.name.equals("field1")) {
83-
return new String[]{"field_1", "Field1"};
58+
field.fromNames = new String[]{"field_1", "Field1"};
59+
return true;
8460
}
85-
return null;
61+
return false;
8662
}
8763
});
8864
JsonIterator iter = JsonIterator.parse("{'field_1': 100}{'Field1': 101}".replace('\'', '"'));
@@ -115,11 +91,12 @@ public CustomizedConstructor getConstructor(Class clazz) {
11591
}
11692

11793
@Override
118-
public String[] getBindFrom(Binding field) {
94+
public boolean updateBinding(Binding field) {
11995
if (field.clazz == TestObject5.class && "param1".equals(field.name)) {
120-
return new String[]{"param2"};
96+
field.fromNames = new String[]{"param2"};
97+
return true;
12198
}
122-
return null;
99+
return false;
123100
}
124101
});
125102
JsonIterator iter = JsonIterator.parse("{'param2': 1000}".replace('\'', '"'));
@@ -138,15 +115,42 @@ public void setField(String field) {
138115
public void test_rename_setter() throws IOException {
139116
JsonIterator.registerExtension(new EmptyExtension() {
140117
@Override
141-
public String[] getBindFrom(Binding field) {
118+
public boolean updateBinding(Binding field) {
142119
if (field.clazz == TestObject6.class && field.name.equals("field")) {
143-
return new String[]{"field_1", "Field1"};
120+
field.fromNames = new String[]{"field_1", "Field1"};
121+
return true;
144122
}
145-
return null;
123+
return false;
146124
}
147125
});
148126
JsonIterator iter = JsonIterator.parse("{'field_1': 'hello'}".replace('\'', '"'));
149127
TestObject6 obj = iter.read(TestObject6.class);
150128
assertEquals("hello", obj.field);
151129
}
130+
131+
public static class TestObject7 {
132+
public int field1;
133+
}
134+
135+
public void test_customize_field_decoding_using_extension() throws IOException {
136+
JsonIterator.registerExtension(new EmptyExtension() {
137+
@Override
138+
public boolean updateBinding(Binding field) {
139+
if (field.clazz == TestObject7.class && field.name.equals("field1")) {
140+
field.decoder = new Decoder.IntDecoder() {
141+
142+
@Override
143+
public int decodeInt(JsonIterator iter) throws IOException {
144+
return Integer.valueOf(iter.readString());
145+
}
146+
};
147+
return true;
148+
}
149+
return false;
150+
}
151+
});
152+
JsonIterator iter = JsonIterator.parse("{'field1': '100'}".replace('\'', '"'));
153+
TestObject7 myObject = iter.read(TestObject7.class);
154+
assertEquals(100, myObject.field1);
155+
}
152156
}

0 commit comments

Comments
 (0)