alibaba / fastjson

FASTJSON 2.0.x has been released, faster and more secure, recommend you upgrade.
https://github.com/alibaba/fastjson2/wiki/fastjson_1_upgrade_cn
Apache License 2.0
25.74k stars 6.5k forks source link

JSONCreator 参数不匹配导致反序列化失败 #802

Closed msdx closed 8 years ago

msdx commented 8 years ago

服务端返回的JSON当中,有些字段没有返回,导致反序列化失败。以下是构造方法:

    public CommodityObject(
            @JSONField(name = "id") int id,
            @JSONField(name = "description") String description,
            @JSONField(name = "location") String location,
            @JSONField(name = "location_id") int locationId,
            @JSONField(name = "park") String park,
            @JSONField(name = "park_code") int parkCode,
            @JSONField(name = "face_value") int faceValue,
            @JSONField(name = "ctime") long createTime,
            @JSONField(name = "valid_period") String validPeriod,
            @JSONField(name = "title") String title,
            @JSONField(name = "type") int type,
            @JSONField(name = "ex_type") int exType,
            @JSONField(name = "price") int price,
            @JSONField(name = "status") int status) {

其中location_idpark_code没有传时会报异常:

Caused by: com.alibaba.fastjson.JSONException: create instance error, public com.parkingwang.sdk.coupon.commodity.CommodityObject(int,java.lang.String,java.lang.String,int,java.lang.String,int,int,long,java.lang.String,java.lang.String,int,int,int,int)
    at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:611)
    at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:189)
    at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:185)
    at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:614)
    at com.alibaba.fastjson.JSON.parseObject(JSON.java:339)
    at com.alibaba.fastjson.JSON.parseObject(JSON.java:243)
    at com.alibaba.fastjson.JSON.parseObject(JSON.java:456)
    at com.parkingwang.sdk.coupon.commodity.CommodityObjectParser.parse(CommodityObjectParser.java:13)
    at com.parkingwang.sdk.coupon.commodity.CommodityObjectParser.parse(CommodityObjectParser.java:10)
    at com.parkingwang.sdk.http.ext.ListResponseConverter.convert(ListResponseConverter.kt:83)
    at com.parkingwang.sdk.http.ext.ListResponseConverter.convert(ListResponseConverter.kt:14)
    at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:116)
    at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
    at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
    at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:144)
    ... 38 more
Caused by: java.lang.IllegalArgumentException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:608)
    ... 52 more

另外,还发现,如果缺少的字段为String时能够正常创建实例,而在上面的例子中为int时创建实例失败。

msdx commented 8 years ago

在JavaBeanDeserializer类的deserialze方法中,其中以下代码:

                FieldInfo[] fieldInfoList = beanInfo.fields;
                int size = fieldInfoList.length;
                Object[] params = new Object[size];
                for (int i = 0; i < size; ++i) {
                    FieldInfo fieldInfo = fieldInfoList[i];
                    params[i] = fieldValues.get(fieldInfo.name);
                }

                if (beanInfo.creatorConstructor != null) {
                    try {
                        object = beanInfo.creatorConstructor.newInstance(params);
                    } catch (Exception e) {
                        throw new JSONException("create instance error, "
                                                + beanInfo.creatorConstructor.toGenericString(), e);
                    }
                } else if (beanInfo.factoryMethod != null) {
                    try {
                        object = beanInfo.factoryMethod.invoke(null, params);
                    } catch (Exception e) {
                        throw new JSONException("create factory method error, " + beanInfo.factoryMethod.toString(), e);
                    }
                }

这里的params用于作为构造方法中的参数传入,它的值是根据前面的fieldValues来获取的,但是如果不存在对应字段的话,它的值就为null,而如果缺少对应字段的参数为基本类型,不能为null,就导致后面的newInstance失败。在这里我认为从fieldValues中获取值时,如果获取不到,应该判断是否为基本类型,为基本类型的话应该赋值为0或false等基本类型的值,而不是直接赋为null。

wenshao commented 8 years ago

问题解决,请等待1.2.17发布吧

msdx commented 8 years ago

@wenshao 您好,请问这个问题的修复包含在了android版本了吗?

msdx commented 7 years ago

I need this fix to be included in android version.