From ca5f8a3c4c839cad510b286239adbba1bb8aed8f Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 16 Jan 2017 23:52:12 +0800 Subject: [PATCH] bug fixed generic support. issue #998 --- .../parser/ListTypeFieldDeserializer.java | 16 ++----- .../fastjson/serializer/CollectionCodec.java | 26 ++-------- .../fastjson/serializer/ListSerializer.java | 7 ++- .../com/alibaba/fastjson/util/TypeUtils.java | 28 +++++++++++ .../com/alibaba/json/bvt/bug/Issue998.java | 25 +++++++++- .../json/bvt/bug/Issue998_private.java | 48 +++++++++++++++++++ 6 files changed, 109 insertions(+), 41 deletions(-) create mode 100644 src/test/java/com/alibaba/json/bvt/bug/Issue998_private.java diff --git a/src/main/java/com/alibaba/fastjson/parser/ListTypeFieldDeserializer.java b/src/main/java/com/alibaba/fastjson/parser/ListTypeFieldDeserializer.java index 0201da02b..ec0c9c741 100755 --- a/src/main/java/com/alibaba/fastjson/parser/ListTypeFieldDeserializer.java +++ b/src/main/java/com/alibaba/fastjson/parser/ListTypeFieldDeserializer.java @@ -12,6 +12,7 @@ import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; import com.alibaba.fastjson.util.FieldInfo; import com.alibaba.fastjson.util.ParameterizedTypeImpl; +import com.alibaba.fastjson.util.TypeUtils; class ListTypeFieldDeserializer extends FieldDeserializer { @@ -24,22 +25,11 @@ class ListTypeFieldDeserializer extends FieldDeserializer { Type fieldType = fieldInfo.fieldType; Class fieldClass= fieldInfo.fieldClass; - if (fieldType instanceof ParameterizedType) { - Type argType = ((ParameterizedType) fieldInfo.fieldType).getActualTypeArguments()[0]; - if (argType instanceof WildcardType) { - WildcardType wildcardType = (WildcardType) argType; - Type[] upperBounds = wildcardType.getUpperBounds(); - if (upperBounds.length == 1) { - argType = upperBounds[0]; - } - } - this.itemType = argType; - array = false; - } else if (fieldClass.isArray()) { + if (fieldClass.isArray()) { this.itemType = fieldClass.getComponentType(); array = true; } else { - this.itemType = Object.class; + this.itemType = TypeUtils.getCollectionItemType(fieldType); array = false; } } diff --git a/src/main/java/com/alibaba/fastjson/serializer/CollectionCodec.java b/src/main/java/com/alibaba/fastjson/serializer/CollectionCodec.java index 74e02bec0..041fd033e 100755 --- a/src/main/java/com/alibaba/fastjson/serializer/CollectionCodec.java +++ b/src/main/java/com/alibaba/fastjson/serializer/CollectionCodec.java @@ -31,6 +31,7 @@ import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.parser.DefaultJSONParser; import com.alibaba.fastjson.parser.JSONToken; import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; +import com.alibaba.fastjson.util.TypeUtils; /** * @author wenshao[szujobs@hotmail.com] @@ -57,10 +58,7 @@ public class CollectionCodec implements ObjectSerializer, ObjectDeserializer { Type elementType = null; if ((out.features & SerializerFeature.WriteClassName.mask) != 0) { - if (fieldType instanceof ParameterizedType) { - ParameterizedType param = (ParameterizedType) fieldType; - elementType = param.getActualTypeArguments()[0]; - } + elementType = TypeUtils.getCollectionItemType(fieldType); } Collection collection = (Collection) object; @@ -168,24 +166,8 @@ public class CollectionCodec implements ObjectSerializer, ObjectDeserializer { throw new JSONException("create instane error, class " + rawClass.getName()); } } - - Type itemType = null; - if (type instanceof ParameterizedType) { - itemType = ((ParameterizedType) type).getActualTypeArguments()[0]; - } else { - Class clazz = null; - if (type instanceof Class // - && !(clazz = (Class) type).getName().startsWith("java.")) { - Type superClass = clazz.getGenericSuperclass(); - if (superClass instanceof ParameterizedType) { - itemType = ((ParameterizedType) superClass).getActualTypeArguments()[0]; - } - } - - if (itemType == null) { - itemType = Object.class; - } - } + + Type itemType = TypeUtils.getCollectionItemType(type); parser.parseArray(itemType, list, fieldName); return (T) list; diff --git a/src/main/java/com/alibaba/fastjson/serializer/ListSerializer.java b/src/main/java/com/alibaba/fastjson/serializer/ListSerializer.java index 918b62f87..3f82bbd3a 100644 --- a/src/main/java/com/alibaba/fastjson/serializer/ListSerializer.java +++ b/src/main/java/com/alibaba/fastjson/serializer/ListSerializer.java @@ -15,6 +15,8 @@ */ package com.alibaba.fastjson.serializer; +import com.alibaba.fastjson.util.TypeUtils; + import java.io.IOException; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -36,10 +38,7 @@ public final class ListSerializer implements ObjectSerializer { Type elementType = null; if (writeClassName) { - if (fieldType instanceof ParameterizedType) { - ParameterizedType param = (ParameterizedType) fieldType; - elementType = param.getActualTypeArguments()[0]; - } + elementType = TypeUtils.getCollectionItemType(fieldType); } if (object == null) { diff --git a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java index d2643e99c..c9db5b713 100755 --- a/src/main/java/com/alibaba/fastjson/util/TypeUtils.java +++ b/src/main/java/com/alibaba/fastjson/util/TypeUtils.java @@ -1336,6 +1336,34 @@ public class TypeUtils { : null; } + public static Type getCollectionItemType(Type fieldType) { + Type itemType = null; + Class clazz = null; + if (fieldType instanceof ParameterizedType) { + Type actualTypeArgument = ((ParameterizedType) fieldType).getActualTypeArguments()[0]; + + if (actualTypeArgument instanceof WildcardType) { + WildcardType wildcardType = (WildcardType) actualTypeArgument; + Type[] upperBounds = wildcardType.getUpperBounds(); + if (upperBounds.length == 1) { + actualTypeArgument = upperBounds[0]; + } + } + + itemType = actualTypeArgument; + } else if (fieldType instanceof Class // + && !(clazz = (Class) fieldType).getName().startsWith("java.")) { + Type superClass = clazz.getGenericSuperclass(); + itemType = TypeUtils.getCollectionItemType(superClass); + } + + if (itemType == null) { + itemType = Object.class; + } + + return itemType; + } + // public static long fnv_hash(char[] chars) { // long hash = 0x811c9dc5; // for (int i = 0; i < chars.length; ++i) { diff --git a/src/test/java/com/alibaba/json/bvt/bug/Issue998.java b/src/test/java/com/alibaba/json/bvt/bug/Issue998.java index e744fd0c1..ac1841127 100644 --- a/src/test/java/com/alibaba/json/bvt/bug/Issue998.java +++ b/src/test/java/com/alibaba/json/bvt/bug/Issue998.java @@ -2,8 +2,10 @@ package com.alibaba.json.bvt.bug; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; +import com.alibaba.fastjson.serializer.SerializerFeature; import junit.framework.TestCase; +import java.lang.reflect.Field; import java.util.List; /** @@ -15,7 +17,18 @@ public class Issue998 extends TestCase { assertNotNull(model); assertNotNull(model.items); assertEquals(1, model.items.size()); - assertEquals(123, model.items.get(0).id); + assertEquals(123, model.items.get(0).getId()); + + String json = JSON.toJSONString(model, SerializerFeature.NotWriteRootClassName, SerializerFeature.WriteClassName); + assertEquals("{\"items\":[{\"id\":123}]}", json); + } + + public void test_for_issue_1() throws Exception { + Field field = Model.class.getField("items"); + List items = (List ) JSON.parseObject("[{\"id\":123}]", field.getGenericType()); + assertNotNull(items); + assertEquals(1, items.size()); + assertEquals(123, items.get(0).id); } public static class Model { @@ -23,6 +36,14 @@ public class Issue998 extends TestCase { } public static class Item { - public int id; + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } } } diff --git a/src/test/java/com/alibaba/json/bvt/bug/Issue998_private.java b/src/test/java/com/alibaba/json/bvt/bug/Issue998_private.java new file mode 100644 index 000000000..7ac6def69 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/bug/Issue998_private.java @@ -0,0 +1,48 @@ +package com.alibaba.json.bvt.bug; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.serializer.SerializerFeature; +import junit.framework.TestCase; + +import java.lang.reflect.Field; +import java.util.List; + +/** + * Created by wenshao on 16/01/2017. + */ +public class Issue998_private extends TestCase { + public void test_for_issue() throws Exception { + Model model = JSON.parseObject("{\"items\":[{\"id\":123}]}", Model.class); + assertNotNull(model); + assertNotNull(model.items); + assertEquals(1, model.items.size()); + assertEquals(123, model.items.get(0).getId()); + + String json = JSON.toJSONString(model, SerializerFeature.NotWriteRootClassName, SerializerFeature.WriteClassName); + assertEquals("{\"items\":[{\"id\":123}]}", json); + } + + public void test_for_issue_1() throws Exception { + Field field = Model.class.getField("items"); + List items = (List ) JSON.parseObject("[{\"id\":123}]", field.getGenericType()); + assertNotNull(items); + assertEquals(1, items.size()); + assertEquals(123, items.get(0).id); + } + + private static class Model { + public List items; + } + + private static class Item { + private int id; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + } +}