@@ -28,14 +28,15 @@ class Codegen {
28
28
put (Long .class .getName (), "Long.valueOf(iter.readLong())" );
29
29
put (String .class .getName (), "iter.readString()" );
30
30
}};
31
- final static Set <Class > WITH_CAPACITY_COLLECTION_CLASSES = new HashSet <Class >(){{
31
+ final static Set <Class > WITH_CAPACITY_COLLECTION_CLASSES = new HashSet <Class >() {{
32
32
add (ArrayList .class );
33
33
add (HashSet .class );
34
+ add (Vector .class );
34
35
}};
35
36
static volatile Map <String , Decoder > cache = new HashMap <>();
36
37
static ClassPool pool = ClassPool .getDefault ();
37
38
38
- static Decoder getDecoder (String cacheKey , Type type , Type [] typeArgs ) {
39
+ static Decoder getDecoder (String cacheKey , Type type , Type ... typeArgs ) {
39
40
Decoder decoder = cache .get (cacheKey );
40
41
if (decoder != null ) {
41
42
return decoder ;
@@ -56,7 +57,7 @@ private synchronized static Decoder gen(String cacheKey, Type type, Type[] typeA
56
57
} else {
57
58
clazz = (Class ) type ;
58
59
}
59
- String source = genSource (cacheKey , typeArgs , clazz );
60
+ String source = genSource (cacheKey , clazz , typeArgs );
60
61
try {
61
62
CtClass ctClass = pool .makeClass (cacheKey );
62
63
ctClass .setInterfaces (new CtClass []{pool .get (Decoder .class .getName ())});
@@ -72,24 +73,68 @@ private synchronized static Decoder gen(String cacheKey, Type type, Type[] typeA
72
73
}
73
74
}
74
75
75
- private static String genSource (String cacheKey , Type [] typeArgs , Class clazz ) {
76
+ private static String genSource (String cacheKey , Class clazz , Type [] typeArgs ) {
77
+ if (Object .class == clazz ) {
78
+ throw new IllegalArgumentException ("can not bind to Object.class, parser need schema" );
79
+ }
80
+ if (NATIVE_READS .containsKey (clazz .getName ())) {
81
+ return genNative (clazz );
82
+ }
76
83
if (clazz .isArray ()) {
77
84
return genArray (clazz );
78
- } else if (Collection .class .isAssignableFrom (clazz )) {
79
- Class compType = (Class ) typeArgs [0 ];
85
+ }
86
+ if (Map .class .isAssignableFrom (clazz )) {
87
+ if (typeArgs .length != 2 ) {
88
+ throw new IllegalArgumentException (
89
+ "can not bind to generic collection without argument types, " +
90
+ "try syntax like TypeLiteral<Map<String, String>>{}" );
91
+ }
92
+ if (typeArgs [0 ] != String .class ) {
93
+ throw new IllegalArgumentException ("map key must be String" );
94
+ }
95
+ if (clazz == Map .class ) {
96
+ clazz = HashMap .class ;
97
+ }
98
+ return genMap (clazz , typeArgs [1 ]);
99
+ }
100
+ if (Collection .class .isAssignableFrom (clazz )) {
101
+ if (typeArgs .length != 1 ) {
102
+ throw new IllegalArgumentException (
103
+ "can not bind to generic collection without argument types, " +
104
+ "try syntax like TypeLiteral<List<Integer>>{}" );
105
+ }
80
106
if (clazz == List .class ) {
81
107
clazz = ArrayList .class ;
82
108
} else if (clazz == Set .class ) {
83
109
clazz = HashSet .class ;
84
110
}
85
111
if (WITH_CAPACITY_COLLECTION_CLASSES .contains (clazz )) {
86
- return genCollectionWithCapacity (clazz , compType );
112
+ return genCollectionWithCapacity (clazz , typeArgs [ 0 ] );
87
113
} else {
88
- return genCollection (clazz , compType );
114
+ return genCollection (clazz , typeArgs [ 0 ] );
89
115
}
90
- } else {
91
- return genObject (clazz , cacheKey );
92
116
}
117
+ return genObject (clazz , cacheKey );
118
+ }
119
+
120
+ private static String genMap (Class clazz , Type valueType ) {
121
+ StringBuilder lines = new StringBuilder ();
122
+ append (lines , "public Object decode(java.lang.reflect.Type type, com.github.jsoniter.Jsoniter iter) {" );
123
+ append (lines , "{{clazz}} map = new {{clazz}}();" );
124
+ append (lines , "for (String field = iter.readObject(); field != null; field = iter.readObject()) {" );
125
+ append (lines , "map.put(field, {{op}});" );
126
+ append (lines , "}" );
127
+ append (lines , "return map;" );
128
+ append (lines , "}" );
129
+ return lines .toString ().replace ("{{clazz}}" , clazz .getName ()).replace ("{{op}}" , genReadOp (valueType ));
130
+ }
131
+
132
+ private static String genNative (Class clazz ) {
133
+ StringBuilder lines = new StringBuilder ();
134
+ append (lines , "public Object decode(java.lang.reflect.Type type, com.github.jsoniter.Jsoniter iter) {" );
135
+ append (lines , "return " + NATIVE_READS .get (clazz .getName ()) + ";" );
136
+ append (lines , "}" );
137
+ return lines .toString ();
93
138
}
94
139
95
140
public static void addNewDecoder (String cacheKey , Decoder decoder ) {
@@ -164,48 +209,63 @@ private static void addFieldDispatch(StringBuilder lines, int len, int i, Map<By
164
209
private static void genField (StringBuilder lines , Field field , String cacheKey ) {
165
210
String fieldCacheKey = field .getName () + "@" + cacheKey ;
166
211
String fieldTypeName = field .getType ().getCanonicalName ();
167
- String nativeRead = NATIVE_READS .get (fieldTypeName );
168
212
if (cache .containsKey (fieldCacheKey )) {
169
213
append (lines , String .format ("obj.%s = (%s)iter.read(\" %s\" , %s.class);" ,
170
214
field .getName (), fieldTypeName , fieldCacheKey , fieldTypeName ));
171
215
return ;
172
216
}
173
- if (nativeRead == null ) {
174
- if (field .getGenericType () instanceof ParameterizedType ) {
175
- ParameterizedType pType = (ParameterizedType ) field .getGenericType ();
176
- Class arg1 = (Class ) pType .getActualTypeArguments ()[0 ];
177
- append (lines , String .format ("obj.%s = (%s)iter.read(\" %s\" , %s.class, %s.class);" ,
178
- field .getName (), fieldTypeName , TypeLiteral .generateCacheKey (field .getGenericType ()),
179
- fieldTypeName , arg1 .getName ()));
180
- } else {
181
- append (lines , String .format ("obj.%s = (%s)iter.read(%s.class);" ,
182
- field .getName (), fieldTypeName , fieldTypeName ));
217
+ append (lines , String .format ("obj.%s = %s;" , field .getName (), genReadOp (field .getGenericType ())));
218
+ }
219
+
220
+ private static String genReadOp (Type type ) {
221
+ if (type instanceof Class ) {
222
+ Class clazz = (Class ) type ;
223
+ String nativeRead = NATIVE_READS .get (clazz .getName ());
224
+ if (nativeRead != null ) {
225
+ return nativeRead ;
183
226
}
184
- } else {
185
- append ( lines , String . format ( "obj.%s = %s;" , field .getName (), nativeRead ));
227
+ return String . format ( "(%s)iter.read( \" %s \" , %s.class)" ,
228
+ clazz .getName (), TypeLiteral . generateCacheKey ( clazz ), clazz . getName ( ));
186
229
}
230
+ if (type instanceof ParameterizedType ) {
231
+ ParameterizedType pType = (ParameterizedType ) type ;
232
+ Class clazz = (Class ) pType .getRawType ();
233
+ Type [] args = pType .getActualTypeArguments ();
234
+ switch (args .length ) {
235
+ case 1 :
236
+ return String .format ("(%s)iter.read(\" %s\" , %s.class, %s.class);" ,
237
+ clazz .getName (), TypeLiteral .generateCacheKey (type ),
238
+ clazz .getName (), ((Class ) args [0 ]).getName ());
239
+ case 2 :
240
+ return String .format ("(%s)iter.read(\" %s\" , %s.class, %s.class, %s.class);" ,
241
+ clazz .getName (), TypeLiteral .generateCacheKey (type ),
242
+ clazz .getName (), ((Class ) args [0 ]).getName (), ((Class ) args [1 ]).getName ());
243
+ default :
244
+ throw new IllegalArgumentException ("unsupported number of type arguments: " + type );
245
+ }
246
+ }
247
+ throw new IllegalArgumentException ("unsupported type: " + type );
187
248
}
188
249
189
250
private static String genArray (Class clazz ) {
190
251
Class compType = clazz .getComponentType ();
191
252
if (compType .isArray ()) {
192
253
throw new IllegalArgumentException ("nested array not supported: " + clazz .getCanonicalName ());
193
254
}
194
- String nativeRead = NATIVE_READS .get (compType .getName ());
195
255
StringBuilder lines = new StringBuilder ();
196
256
append (lines , "public Object decode(java.lang.reflect.Type type, com.github.jsoniter.Jsoniter iter) {" );
197
257
append (lines , "if (!iter.readArray()) {" );
198
258
append (lines , "return new {{comp}}[0];" );
199
259
append (lines , "}" );
200
- append (lines , "{{comp}} a1 = ({{comp}}) {{op}};" );
260
+ append (lines , "{{comp}} a1 = {{op}};" );
201
261
append (lines , "if (!iter.readArray()) {" );
202
262
append (lines , "return new {{comp}}[]{ a1 };" );
203
263
append (lines , "}" );
204
- append (lines , "{{comp}} a2 = ({{comp}}) {{op}};" );
264
+ append (lines , "{{comp}} a2 = {{op}};" );
205
265
append (lines , "if (!iter.readArray()) {" );
206
266
append (lines , "return new {{comp}}[]{ a1, a2 };" );
207
267
append (lines , "}" );
208
- append (lines , "{{comp}} a3 = ({{comp}}) {{op}};" );
268
+ append (lines , "{{comp}} a3 = {{op}};" );
209
269
append (lines , "if (!iter.readArray()) {" );
210
270
append (lines , "return new {{comp}}[]{ a1, a2, a3 };" );
211
271
append (lines , "}" );
@@ -222,119 +282,103 @@ private static String genArray(Class clazz) {
222
282
append (lines , "System.arraycopy(arr, 0, newArr, 0, arr.length);" );
223
283
append (lines , "arr = newArr;" );
224
284
append (lines , "}" );
225
- append (lines , "arr[i++] = ({{comp}}) {{op}};" );
285
+ append (lines , "arr[i++] = {{op}};" );
226
286
append (lines , "}" );
227
287
append (lines , "{{comp}}[] result = new {{comp}}[i];" );
228
288
append (lines , "System.arraycopy(arr, 0, result, 0, i);" );
229
289
append (lines , "return result;" );
230
290
append (lines , "}" );
231
- String op = String .format ("iter.read(%s.class)" , compType .getCanonicalName ());
232
- if (nativeRead != null ) {
233
- op = nativeRead ;
234
- }
235
291
return lines .toString ().replace (
236
292
"{{comp}}" , compType .getCanonicalName ()).replace (
237
- "{{op}}" , op );
293
+ "{{op}}" , genReadOp ( compType ) );
238
294
}
239
295
240
- private static String genCollectionWithCapacity (Class clazz , Class compType ) {
241
- String nativeRead = NATIVE_READS .get (compType .getName ());
296
+ private static String genCollectionWithCapacity (Class clazz , Type compType ) {
242
297
StringBuilder lines = new StringBuilder ();
243
298
append (lines , "public Object decode(java.lang.reflect.Type type, com.github.jsoniter.Jsoniter iter) {" );
244
299
append (lines , "if (!iter.readArray()) {" );
245
300
append (lines , "return new {{clazz}}(0);" );
246
301
append (lines , "}" );
247
- append (lines , "{{comp}} a1 = ({{comp}}) {{op}};" );
302
+ append (lines , "Object a1 = {{op}};" );
248
303
append (lines , "if (!iter.readArray()) {" );
249
304
append (lines , "{{clazz}} obj = new {{clazz}}(1);" );
250
305
append (lines , "obj.add(a1);" );
251
306
append (lines , "return obj;" );
252
307
append (lines , "}" );
253
- append (lines , "{{comp}} a2 = ({{comp}}) {{op}};" );
308
+ append (lines , "Object a2 = {{op}};" );
254
309
append (lines , "if (!iter.readArray()) {" );
255
310
append (lines , "{{clazz}} obj = new {{clazz}}(2);" );
256
311
append (lines , "obj.add(a1);" );
257
312
append (lines , "obj.add(a2);" );
258
313
append (lines , "return obj;" );
259
314
append (lines , "}" );
260
- append (lines , "{{comp}} a3 = ({{comp}}) {{op}};" );
315
+ append (lines , "Object a3 = {{op}};" );
261
316
append (lines , "if (!iter.readArray()) {" );
262
317
append (lines , "{{clazz}} obj = new {{clazz}}(3);" );
263
318
append (lines , "obj.add(a1);" );
264
319
append (lines , "obj.add(a2);" );
265
320
append (lines , "obj.add(a3);" );
266
321
append (lines , "return obj;" );
267
322
append (lines , "}" );
268
- append (lines , "{{comp}} a4 = ({{comp}}) {{op}};" );
323
+ append (lines , "Object a4 = {{op}};" );
269
324
append (lines , "{{clazz}} obj = new {{clazz}}(8);" );
270
325
append (lines , "obj.add(a1);" );
271
326
append (lines , "obj.add(a2);" );
272
327
append (lines , "obj.add(a3);" );
273
328
append (lines , "obj.add(a4);" );
274
329
append (lines , "int i = 4;" );
275
330
append (lines , "while (iter.readArray()) {" );
276
- append (lines , "obj.add(({{comp}}) {{op}});" );
331
+ append (lines , "obj.add({{op}});" );
277
332
append (lines , "}" );
278
333
append (lines , "return obj;" );
279
334
append (lines , "}" );
280
- String op = String .format ("iter.read(%s.class)" , compType .getCanonicalName ());
281
- if (nativeRead != null ) {
282
- op = nativeRead ;
283
- }
284
335
return lines .toString ().replace (
285
336
"{{clazz}}" , clazz .getName ()).replace (
286
- "{{comp}}" , compType .getCanonicalName ()).replace (
287
- "{{op}}" , op );
337
+ "{{op}}" , genReadOp (compType ));
288
338
}
289
339
290
- private static String genCollection (Class clazz , Class compType ) {
291
- String nativeRead = NATIVE_READS .get (compType .getName ());
340
+ private static String genCollection (Class clazz , Type compType ) {
292
341
StringBuilder lines = new StringBuilder ();
293
342
append (lines , "public Object decode(java.lang.reflect.Type type, com.github.jsoniter.Jsoniter iter) {" );
294
343
append (lines , "if (!iter.readArray()) {" );
295
344
append (lines , "return new {{clazz}}();" );
296
345
append (lines , "}" );
297
- append (lines , "{{comp}} a1 = ({{comp}}) {{op}};" );
346
+ append (lines , "Object a1 = {{op}};" );
298
347
append (lines , "if (!iter.readArray()) {" );
299
348
append (lines , "{{clazz}} obj = new {{clazz}}();" );
300
349
append (lines , "obj.add(a1);" );
301
350
append (lines , "return obj;" );
302
351
append (lines , "}" );
303
- append (lines , "{{comp}} a2 = ({{comp}}) {{op}};" );
352
+ append (lines , "Object a2 = {{op}};" );
304
353
append (lines , "if (!iter.readArray()) {" );
305
354
append (lines , "{{clazz}} obj = new {{clazz}}();" );
306
355
append (lines , "obj.add(a1);" );
307
356
append (lines , "obj.add(a2);" );
308
357
append (lines , "return obj;" );
309
358
append (lines , "}" );
310
- append (lines , "{{comp}} a3 = ({{comp}}) {{op}};" );
359
+ append (lines , "Object a3 = {{op}};" );
311
360
append (lines , "if (!iter.readArray()) {" );
312
361
append (lines , "{{clazz}} obj = new {{clazz}}();" );
313
362
append (lines , "obj.add(a1);" );
314
363
append (lines , "obj.add(a2);" );
315
364
append (lines , "obj.add(a3);" );
316
365
append (lines , "return obj;" );
317
366
append (lines , "}" );
318
- append (lines , "{{comp}} a4 = ({{comp}}) {{op}};" );
367
+ append (lines , "Object a4 = {{op}};" );
319
368
append (lines , "{{clazz}} obj = new {{clazz}}();" );
320
369
append (lines , "obj.add(a1);" );
321
370
append (lines , "obj.add(a2);" );
322
371
append (lines , "obj.add(a3);" );
323
372
append (lines , "obj.add(a4);" );
324
373
append (lines , "int i = 4;" );
325
374
append (lines , "while (iter.readArray()) {" );
326
- append (lines , "obj.add(({{comp}}) {{op}});" );
375
+ append (lines , "obj.add({{op}});" );
327
376
append (lines , "}" );
328
377
append (lines , "return obj;" );
329
378
append (lines , "}" );
330
- String op = String .format ("iter.read(%s.class)" , compType .getCanonicalName ());
331
- if (nativeRead != null ) {
332
- op = nativeRead ;
333
- }
334
379
return lines .toString ().replace (
335
380
"{{clazz}}" , clazz .getName ()).replace (
336
- "{{comp}}" , compType .getCanonicalName ()).replace (
337
- "{{op}}" , op );
381
+ "{{op}}" , genReadOp (compType ));
338
382
}
339
383
340
384
private static void append (StringBuilder lines , String str ) {
0 commit comments