Skip to content

Commit afdc004

Browse files
committed
improved first time codec & decode.
1 parent a7ef6dd commit afdc004

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3576
-66
lines changed

src/main/java/com/alibaba/fastjson/parser/JavaBeanInfo.java

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@
66
import java.lang.reflect.Method;
77
import java.lang.reflect.Modifier;
88
import java.lang.reflect.Type;
9-
import java.util.ArrayList;
10-
import java.util.Arrays;
11-
import java.util.Collection;
12-
import java.util.List;
13-
import java.util.Map;
9+
import java.util.*;
1410

1511
import com.alibaba.fastjson.JSONException;
1612
import com.alibaba.fastjson.PropertyNamingStrategy;
@@ -201,6 +197,7 @@ public static JavaBeanInfo build(Class<?> clazz, //
201197
PropertyNamingStrategy propertyNamingStrategy
202198
) {
203199
List<FieldInfo> fieldList = new ArrayList<FieldInfo>();
200+
Map<Class<?>, Field[]> classFieldCache = new HashMap<Class<?>, Field[]>();
204201

205202
// DeserializeBeanInfo beanInfo = null;
206203
Constructor<?> defaultConstructor = null;
@@ -226,9 +223,40 @@ public static JavaBeanInfo build(Class<?> clazz, //
226223

227224
Constructor<?> creatorConstructor = null;
228225
Method factoryMethod = null;
229-
Method[] methods = fieldOnly //
230-
? null //
231-
: clazz.getMethods();
226+
227+
Method[] methods;
228+
if (fieldOnly) {
229+
methods = null;
230+
} else {
231+
List<Method> methodList = new ArrayList<Method>();
232+
233+
for (Class cls = clazz; cls != null && cls != Object.class; cls = cls.getSuperclass()) {
234+
Method[] declaredMethods = cls.getDeclaredMethods();
235+
for (Method method : declaredMethods) {
236+
int modifier = method.getModifiers();
237+
238+
if ((modifier & Modifier.STATIC) != 0) {
239+
if (method.isAnnotationPresent(JSONCreator.class)) {
240+
if (factoryMethod != null) {
241+
throw new JSONException("multi-json creator");
242+
}
243+
244+
factoryMethod = method;
245+
}
246+
continue;
247+
}
248+
249+
if ((modifier & Modifier.PRIVATE) != 0 || (modifier & Modifier.NATIVE) != 0 || (modifier & Modifier.PROTECTED) != 0) {
250+
continue;
251+
}
252+
253+
methodList.add(method);
254+
}
255+
}
256+
257+
methods = new Method[methodList.size()];
258+
methodList.toArray(methods);
259+
}
232260

233261
final Field[] declaredFields = clazz.getDeclaredFields();
234262

@@ -271,7 +299,7 @@ public static JavaBeanInfo build(Class<?> clazz, //
271299

272300
Class<?> fieldClass = parameterTypes[i];
273301
Type fieldType = getGenericParameterTypes[i];
274-
Field field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields);
302+
Field field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields, classFieldCache);
275303

276304
if (field != null) {
277305
TypeUtils.setAccessible(clazz, field, classModifiers);
@@ -299,26 +327,6 @@ public static JavaBeanInfo build(Class<?> clazz, //
299327
JSONType jsonType = jsonTypeSupport ? clazz.getAnnotation(JSONType.class) : null;
300328
return new JavaBeanInfo(clazz, null, creatorConstructor, null, fields, sortedFields, jsonType);
301329
}
302-
303-
{
304-
for (Method method : methods) {
305-
if ((!Modifier.isStatic(method.getModifiers())) //
306-
|| !clazz.isAssignableFrom(method.getReturnType()) //
307-
) {
308-
continue;
309-
}
310-
311-
JSONCreator annotation = method.getAnnotation(JSONCreator.class);
312-
if (annotation != null) {
313-
if (factoryMethod != null) {
314-
throw new JSONException("multi-json creator");
315-
}
316-
317-
factoryMethod = method;
318-
break;
319-
}
320-
}
321-
}
322330

323331
if (factoryMethod != null) {
324332
TypeUtils.setAccessible(clazz, factoryMethod, classModifiers);
@@ -345,7 +353,7 @@ public static JavaBeanInfo build(Class<?> clazz, //
345353

346354
Class<?> fieldClass = parameterTypes[i];
347355
Type fieldType = genericParameterTypes[i];
348-
Field field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields);
356+
Field field = TypeUtils.getField(clazz, fieldAnnotation.name(), declaredFields, classFieldCache);
349357
final int ordinal = fieldAnnotation.ordinal();
350358
final int serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures());
351359
FieldInfo fieldInfo = new FieldInfo(fieldAnnotation.name() //
@@ -386,22 +394,18 @@ public static JavaBeanInfo build(Class<?> clazz, //
386394
for (Method method : methods) {
387395
int ordinal = 0, serialzeFeatures = 0;
388396
String methodName = method.getName();
389-
if (methodName.length() < 4 //
390-
|| Modifier.isStatic(method.getModifiers())
391-
) {
397+
if (methodName.length() < 4) {
392398
continue;
393399
}
394400

395-
// support builder set
396-
397401
Class<?> returnType = method.getReturnType();
398402
if ((!(returnType == Void.TYPE || returnType == method.getDeclaringClass())) //
399403
|| method.getParameterTypes().length != 1 //
400-
|| method.getDeclaringClass() == Object.class //
401404
) {
402405
continue;
403406
}
404407

408+
// support builder set
405409
JSONField annotation = jsonFieldSupport ? method.getAnnotation(JSONField.class) : null;
406410

407411
if (annotation == null && jsonFieldSupport) {
@@ -458,11 +462,11 @@ public static JavaBeanInfo build(Class<?> clazz, //
458462
continue;
459463
}
460464

461-
Field field = TypeUtils.getField(clazz, propertyName, declaredFields);
465+
Field field = TypeUtils.getField(clazz, propertyName, declaredFields, classFieldCache);
462466
if (field == null && method.getParameterTypes()[0] == boolean.class) {
463467
String isFieldName = "is" + Character.toUpperCase(propertyName.charAt(0))
464468
+ propertyName.substring(1);
465-
field = TypeUtils.getField(clazz, isFieldName, declaredFields);
469+
field = TypeUtils.getField(clazz, isFieldName, declaredFields, classFieldCache);
466470
}
467471

468472
if (field != null) {
@@ -593,15 +597,12 @@ public static JavaBeanInfo build(Class<?> clazz, //
593597
}
594598

595599
if (!fieldOnly) {
596-
for (Method method : clazz.getMethods()) {
600+
for (Method method : methods) {
597601
String methodName = method.getName();
598-
if (methodName.length() < 4 //
599-
|| Modifier.isStatic(method.getModifiers()) //
600-
) {
602+
if (methodName.length() < 4) {
601603
continue;
602604
}
603-
604-
605+
605606
if (methodName.startsWith("get") && Character.isUpperCase(methodName.charAt(3))) {
606607
if (method.getParameterTypes().length != 0) {
607608
continue;

src/main/java/com/alibaba/fastjson/util/TypeUtils.java

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import com.alibaba.fastjson.JSONException;
5252
import com.alibaba.fastjson.JSONObject;
5353
import com.alibaba.fastjson.PropertyNamingStrategy;
54+
import com.alibaba.fastjson.annotation.JSONCreator;
5455
import com.alibaba.fastjson.annotation.JSONField;
5556
import com.alibaba.fastjson.annotation.JSONType;
5657
import com.alibaba.fastjson.parser.JSONLexer;
@@ -835,21 +836,43 @@ public static List<FieldInfo> computeGetters(Class<?> clazz, //
835836
boolean fieldGenericSupport, //
836837
PropertyNamingStrategy propertyNamingStrategy) {
837838
Map<String, FieldInfo> fieldInfoMap = new LinkedHashMap<String, FieldInfo>();
839+
Map<Class<?>, Field[]> classFieldCache = new HashMap<Class<?>, Field[]>();
838840

839841
Field[] declaredFields = clazz.getDeclaredFields();
840842
if (!fieldOnly) {
841-
for (Method method : clazz.getMethods()) {
843+
List<Method> methodList = new ArrayList<Method>();
844+
845+
for (Class cls = clazz; cls != null && cls != Object.class; cls = cls.getSuperclass()) {
846+
Method[] declaredMethods = cls.getDeclaredMethods();
847+
for (Method method : declaredMethods) {
848+
int modifier = method.getModifiers();
849+
850+
if ((modifier & Modifier.STATIC) != 0
851+
|| (modifier & Modifier.PRIVATE) != 0
852+
|| (modifier & Modifier.NATIVE) != 0
853+
|| (modifier & Modifier.PROTECTED) != 0) {
854+
continue;
855+
}
856+
857+
if (method.getReturnType().equals(Void.TYPE) //
858+
|| method.getParameterTypes().length != 0 //
859+
|| method.getReturnType() == ClassLoader.class //
860+
|| method.getDeclaringClass() == Object.class //
861+
) {
862+
continue;
863+
}
864+
865+
methodList.add(method);
866+
}
867+
}
868+
869+
870+
for (Method method : methodList) {
842871
String methodName = method.getName();
843872
int ordinal = 0, serialzeFeatures = 0;
844873

845-
if ((method.getModifiers() & Modifier.STATIC) != 0 //
846-
|| method.getReturnType().equals(Void.TYPE) //
847-
|| method.getParameterTypes().length != 0 //
848-
|| method.getReturnType() == ClassLoader.class //
849-
|| method.getDeclaringClass() == Object.class //
850-
|| (methodName.equals("getMetaClass") //
851-
&& method.getReturnType().getName().equals("groovy.lang.MetaClass")) //
852-
) {
874+
if (methodName.equals("getMetaClass") //
875+
&& method.getReturnType().getName().equals("groovy.lang.MetaClass")) {
853876
continue;
854877
}
855878

@@ -914,7 +937,7 @@ public static List<FieldInfo> computeGetters(Class<?> clazz, //
914937
continue;
915938
}
916939

917-
Field field = getField(clazz, propertyName, declaredFields);
940+
Field field = getField(clazz, propertyName, declaredFields, classFieldCache);
918941
JSONField fieldAnnotation = null;
919942
if (field != null) {
920943
fieldAnnotation = jsonFieldSupport ? field.getAnnotation(JSONField.class) : null;
@@ -983,10 +1006,10 @@ public static List<FieldInfo> computeGetters(Class<?> clazz, //
9831006
continue;
9841007
}
9851008

986-
Field field = getField(clazz, propertyName, declaredFields);
1009+
Field field = getField(clazz, propertyName, declaredFields, classFieldCache);
9871010

9881011
if (field == null) {
989-
field = getField(clazz, methodName, declaredFields);
1012+
field = getField(clazz, methodName, declaredFields, classFieldCache);
9901013
}
9911014

9921015
JSONField fieldAnnotation = null;
@@ -1311,37 +1334,51 @@ public static boolean setAccessible(Class<?> clazz, Member member, int classMofi
13111334
return false;
13121335
}
13131336
}
1314-
1337+
13151338
public static Field getField(Class<?> clazz, String fieldName, Field[] declaredFields) {
1316-
Field field = getField0(clazz, fieldName, declaredFields);
1339+
return getField(clazz, fieldName, declaredFields, null);
1340+
}
1341+
1342+
public static Field getField(Class<?> clazz, String fieldName, Field[] declaredFields, Map<Class<?>, Field[]> classFieldCache) {
1343+
Field field = getField0(clazz, fieldName, declaredFields, classFieldCache);
13171344
if (field == null) {
1318-
field = getField0(clazz, "_" + fieldName, declaredFields);
1345+
field = getField0(clazz, "_" + fieldName, declaredFields, classFieldCache);
13191346
}
13201347

13211348
if (field == null) {
1322-
field = getField0(clazz, "m_" + fieldName, declaredFields);
1349+
field = getField0(clazz, "m_" + fieldName, declaredFields, classFieldCache);
13231350
}
13241351

13251352
if (field == null) {
13261353
String mName = "m" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
1327-
field = getField0(clazz, mName, declaredFields);
1354+
field = getField0(clazz, mName, declaredFields, classFieldCache);
13281355
}
13291356

13301357
return field;
13311358
}
13321359

1333-
private static Field getField0(Class<?> clazz, String fieldName, Field[] declaredFields) {
1360+
private static Field getField0(Class<?> clazz, String fieldName, Field[] declaredFields, Map<Class<?>, Field[]> classFieldCache) {
13341361
for (Field item : declaredFields) {
13351362
if (fieldName.equals(item.getName())) {
13361363
return item;
13371364
}
13381365
}
13391366

13401367
Class<?> superClass = clazz.getSuperclass();
1341-
return superClass != null //
1342-
&& superClass != Object.class //
1343-
? getField(superClass, fieldName, superClass.getDeclaredFields()) //
1344-
: null;
1368+
1369+
if (superClass == null || superClass == Object.class) {
1370+
return null;
1371+
}
1372+
1373+
Field[] superClassFields = classFieldCache != null ? classFieldCache.get(superClass) : null;
1374+
if (superClassFields == null) {
1375+
superClassFields = superClass.getDeclaredFields();
1376+
if (classFieldCache != null) {
1377+
classFieldCache.put(superClass, superClassFields);
1378+
}
1379+
}
1380+
1381+
return getField(superClass, fieldName, superClassFields, classFieldCache);
13451382
}
13461383

13471384
public static Type getCollectionItemType(Type fieldType) {

src/test/java/com/alibaba/json/bvt/parser/KaolaTest.java

Lines changed: 21 additions & 0 deletions
Large diffs are not rendered by default.

src/test/java/com/alibaba/json/bvtVO/kaola/TestString.java

Lines changed: 11 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.alibaba.json.bvtVO.kaola.goods;
2+
3+
import java.io.Serializable;
4+
import java.util.List;
5+
6+
/**
7+
* Created by xinyang on 2015/11/23.
8+
*/
9+
public class ActivityListItem implements Serializable {
10+
private static final long serialVersionUID = 3582980766967036213L;
11+
12+
private String activityTitle;
13+
private String activityUrl;
14+
private List<ActivityGoodsImage> goods;
15+
16+
public String getActivityTitle() {
17+
return activityTitle;
18+
}
19+
20+
public void setActivityTitle(String activityTitle) {
21+
this.activityTitle = activityTitle;
22+
}
23+
24+
public String getActivityUrl() {
25+
return activityUrl;
26+
}
27+
28+
public void setActivityUrl(String activityUrl) {
29+
this.activityUrl = activityUrl;
30+
}
31+
32+
public List<ActivityGoodsImage> getGoods() {
33+
return goods;
34+
}
35+
36+
public void setGoods(List<ActivityGoodsImage> goods) {
37+
this.goods = goods;
38+
}
39+
40+
public static class ActivityGoodsImage implements Serializable {
41+
42+
private static final long serialVersionUID = 5406820919987105380L;
43+
private String imgUrl;
44+
private int actualStore;
45+
46+
public int getActualStore() {
47+
return actualStore;
48+
}
49+
50+
public void setActualStore(int actualStore) {
51+
this.actualStore = actualStore;
52+
}
53+
54+
public String getImgUrl() {
55+
return imgUrl;
56+
}
57+
58+
public void setImgUrl(String imgUrl) {
59+
this.imgUrl = imgUrl;
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)