Skip to content
This repository was archived by the owner on Oct 23, 2024. It is now read-only.
This repository was archived by the owner on Oct 23, 2024. It is now read-only.

范型多级别继承的时候, 反序列化会无法精准解析 #2397

Open
@wkkata

Description

@wkkata

之前也提过这个issue,但今天又看了一下发现提的不太好理解。 现在关闭之前的issue重新提一下:
这事最高父类:

public class SuperBaseReply<T> {
    private List<T> items;

    public List<T> getItems() {
        return items;
    }

    public void setItems(List<T> items) {
        this.items = items;
    }
}

这是第二层父类

public class BaseReply<T>extends SuperBaseReply<T> {

}

这是一个简单的pojo

public class Msg implements Serializable{
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Msg(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Msg(){

    }
}

这是最终协议类

public class TestReply extends BaseReply<Msg> {

}

测试代码如下:

String jsonStr = "{"items":[{"id":1,"name":"kata"},{"id":2,"name":"kata2"}]}";
TestReply testReply = JSON.parseObject(jsonStr, new TypeReference() {});
Assert.assertEquals(testReply.getItems().get(0).getId() , 1);

结果报错:

java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.babyfs.servicetk.test.api.Msg

	at com.babyfs.servicetk.test.FastJsonTest.test2LayerDeserilize(FastJsonTest.java:18)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

跟进去看了一下版本(1.2.56):
发现可能的问题如下:
com.alibaba.fastjson.util.FieldInfo(323行)类中在分析范型的时候考虑的不够全面

代码如下:

private static boolean getArgument(Type[] typeArgs, TypeVariable[] typeVariables, Type[] arguments) {
        if (arguments == null || typeVariables.length == 0) {
            return false;
        }

        boolean changed = false;
        for (int i = 0; i < typeArgs.length; ++i) {
            Type typeArg = typeArgs[i];
            if (typeArg instanceof ParameterizedType) {
                ParameterizedType p_typeArg = (ParameterizedType) typeArg;
                Type[] p_typeArg_args = p_typeArg.getActualTypeArguments();
                boolean p_changed = getArgument(p_typeArg_args, typeVariables, arguments);
                if (p_changed) {
                    typeArgs[i] = new ParameterizedTypeImpl(p_typeArg_args, p_typeArg.getOwnerType(), p_typeArg.getRawType());
                    changed = true;
                }
            } else if (typeArg instanceof TypeVariable) {
                for (int j = 0; j < typeVariables.length; ++j) {
                    if (typeArg.equals(typeVariables[j])) {//typeVariables[j]获取的是BaseReply的T,然而范型的持有field在SuperBaseReply中,所以这里肯定是不等于,于是无法正确的设定范型类
                        typeArgs[i] = arguments[j];
                        changed = true;
                    }
                }
            }
        }

        return changed;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Participants

      @wkkata@wenshao

      Issue actions

        范型多级别继承的时候, 反序列化会无法精准解析 · Issue #2397 · alibaba/fastjson