Closed dengyj3 closed 7 years ago
反序列化时的方法封装如下:
//JsonString to JavaBean
public static
如果我是作者,一定不维护,这样的工作。真心变态啊。
能帮忙构建一个重现问题的testcase么?
@dengyj3 已经支持,但是没有重现问题的testcase,无法证明是否已经解决问题
1、String串为如下:
String allMethods = "{\"mList\":[{\"className\":\"com.qa.scftemplate.contract.ISCFServiceForDyjAction\",\"methodName\":\"getArrayInt\",\"parameterSize\":1,\"parameters\":[{\"clazz\":\"[I\",\"clsList\":null,\"isGenericity\":false,\"value\":\"\"}],\"returnType\":\"[I\",\"url\":\"tcp://SCFServiceForDyj/SCFServiceForDyjActionService\"},{\"className\":\"com.qa.scftemplate.contract.ISCFServiceForDyjAction\",\"methodName\":\"getArrayPrimative\",\"parameterSize\":7,\"parameters\":[{\"clazz\":\"[I\",\"clsList\":null,\"isGenericity\":false,\"value\":\"\"},{\"clazz\":\"[F\",\"clsList\":null,\"isGenericity\":false,\"value\":\"\"},{\"clazz\":\"[S\",\"clsList\":null,\"isGenericity\":false,\"value\":\"\"},{\"clazz\":\"[D\",\"clsList\":null,\"isGenericity\":false,\"value\":\"\"},{\"clazz\":\"[J\",\"clsList\":null,\"isGenericity\":false,\"value\":\"\"},{\"clazz\":\"[B\",\"clsList\":null,\"isGenericity\":false,\"value\":\"\"},{\"clazz\":\"[C\",\"clsList\":null,\"isGenericity\":false,\"value\":\"\"}],\"returnType\":\"[Ljava.lang.String;\",\"url\":\"tcp://SCFServiceForDyj/SCFServiceForDyjActionService\"}]}";
2、解析如下:
JsonBean jsonBean = getJsonData(allMethods, JsonBean.class);
3、getJsonData方法如下:
public static <T> T getJsonData(String json, Class<T> clazz){
T jd=(T)JSON.parseObject(json, clazz,
Feature.IgnoreNotMatch,
Feature.AutoCloseSource
);
return jd;
}
4、JsonBean类如下:
import java.util.List;
import com.tfci.interfaceInfo.entity.SCFMethod;
public class JsonBean {
private List<SCFMethod> mList;
public List<SCFMethod> getmList() {
return mList;
}
public void setmList(List<SCFMethod> mList) {
this.mList = mList;
}
}
5、SCFMethod如下:
import java.util.LinkedList;
import java.util.List;
public class SCFMethod {
public String className;
public String url;
public String methodName;
public int parameterSize;
public List<SCFMethodParameter> parameters = new LinkedList<SCFMethodParameter>();
public Class<?> returnType;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public Class<?> getReturnType() {
return returnType;
}
public void setReturnType(Class<?> returnType) {
this.returnType = returnType;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public int getParameterSize() {
return parameterSize;
}
public void setParameterSize(int parameterSize) {
this.parameterSize = parameterSize;
}
public List<SCFMethodParameter> getParameters() {
return parameters;
}
public void setParameters(List<SCFMethodParameter> parameters) {
this.parameters = parameters;
}
}
6、SCFMethodParameter类定义如下:
import java.util.List;
public class SCFMethodParameter implements Cloneable{
public Class<?> clazz;
public Object value;
public boolean isGenericity = false;
public List<Class<?>> clsList;
public boolean getIsGenericity() {
return isGenericity;
}
public void setIsGenericity(boolean isGenericity) {
this.isGenericity = isGenericity;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public Class<?> getClazz() {
return clazz;
}
public void setClazz(Class<?> clazz) {
this.clazz = clazz;
}
public List<Class<?>> getClsList() {
return clsList;
}
public void setClsList(List<Class<?>> clsList) {
this.clsList = clsList;
}
}
7、测试类即把上述1、2放到main方法中执行,报错:
这个case我跑起来没问题,甚至是用1.2.0跑都没问题.
我把case 放到 https://github.com/cyberdak/fastjson-issue 这个项目里面了. @dengyj3 有空看看我的case对不对。你复制到github上面的代码不对,我自己补全了一下。
@cyberdak,您好,谢谢你的回复,
我才发现提交的代码中看不到泛型,只有在编辑模式下才能看到
1、按你的case跑起来确实没问题,但是我的JsonBean.java中是用到泛型,即List中是SCFMethod对象(即private List
public class JsonBean {
private List
2、我复制的代码没有问题,你把泛型都加上试试,我看你的代码中把泛型的具体类都去掉了,在我定义的实体中是有的,难道是因为泛型的问题吗?
3、我把https://github.com/cyberdak/fastjson-issue这里的代码更新了一下,增加了泛型参数,和我本地的代码一致了,看来直接复制代码会把泛型的具体类型会弄丢啊 详见:https://github.com/dengyj3/fastjson-issue/branches
问题已经重现并且解决,预计周末发布新版本解决问题
问题已经修复,请使用1.2.22版本
数据结构如下: JsonBean下面有一个List,
SCFMethod对象中又有一个List对象
SCFParameter中有一个Class<?> clazz
clazz为一个基本类型数组,如int[], float[], short[],double[],long[],byte[],char[]
反序列化时报错:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.wf.mvc.invoke.ActionInvoker.invoke(ActionInvoker.java:76)
at com.wf.mvc.MvcDispatcher.service(MvcDispatcher.java:121)
at com.wf.mvc.MvcFilter.doFilter(MvcFilter.java:67)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at org.jasig.cas.client.util.AssertionThreadLocalFilter.doFilter(AssertionThreadLocalFilter.java:50)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at org.jasig.cas.client.util.HttpServletRequestWrapperFilter.doFilter(HttpServletRequestWrapperFilter.java:71)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at com.sso.client.AbstractTicketValidationFilter.doFilter(AbstractTicketValidationFilter.java:258)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at com.sso.client.AuthenticationFilter.doFilter(AuthenticationFilter.java:161)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at com.sso.client.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:89)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at com.sso.client.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:37)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1482)
at com.sso.session.servlet.filter.session.CacheSessionFilter.doFilter(CacheSessionFilter.java:94)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1474)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:370)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:960)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1021)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.alibaba.fastjson.JSONException
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:625)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:593)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialzeArrayMapping(JavaBeanDeserializer.java:244)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:308)
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.deserializer.JavaBeanDeserializer.parseArray(JavaBeanDeserializer.java:895)
at com.alibaba.fastjson.parser.deserializer.FastjsonASMDeserializer_2_SCFMethod.deserialzeArrayMapping(Unknown Source)
at com.alibaba.fastjson.parser.deserializer.FastjsonASMDeserializer_2_SCFMethod.deserialze(Unknown Source)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:185)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.parseArray(JavaBeanDeserializer.java:895)
at com.alibaba.fastjson.parser.deserializer.FastjsonASMDeserializer_1_JsonBean.deserialzeArrayMapping(Unknown Source)
at com.alibaba.fastjson.parser.deserializer.FastjsonASMDeserializer_1_JsonBean.deserialze(Unknown Source)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:185)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:621)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:339)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:243)
at com.tfci.interfaceInfo.GetInterfaceImpl.getJsonData(GetInterfaceImpl.java:378)
at com.tfci.controllers.CallJarServiceController.getMethods(CallJarServiceController.java:153)
... 46 more
Caused by: java.lang.NullPointerException
at java.lang.reflect.Array.newArray(Native Method)
at java.lang.reflect.Array.newInstance(Array.java:70)
at com.alibaba.fastjson.util.TypeUtils.loadClass(TypeUtils.java:994)
at com.alibaba.fastjson.serializer.MiscCodec.deserialze(MiscCodec.java:295)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:621)
... 64 more
经过分析: 如果是int[]数组,转换成class对象是"[I",在TypeUtils.java中993行 Class<?> componentType = loadClass(className.substring(1), classLoader); 执行完className.substring(1)后为"I", 从而loadClass("I",classLoader)方法时执行到1028行: clazz = Class.forName(className);时由于找不到“I”类而抛了异常,导致反序列化失败;
在源码992行的if中 增加判断if (className.charAt(0) == '[') { String cls = className.substring(1); Class<?> componentType; if(cls.equals("I")){ componentType = loadClass("int", classLoader); }else if(cls.equals("F")){ componentType = loadClass("float", classLoader); }else if(cls.equals("S")){ componentType = loadClass("short", classLoader); }else if(cls.equals("D")){ componentType = loadClass("double", classLoader); }else if(cls.equals("J")){ componentType = loadClass("long", classLoader); }else if(cls.equals("B")){ componentType = loadClass("byte", classLoader); }else if(cls.equals("C")){ componentType = loadClass("char", classLoader); }else{ componentType = loadClass(className.substring(1), classLoader); } return Array.newInstance(componentType, 0).getClass(); }
反序列化正常通过。 版本:1.2.21 反序列化的字符串为: {"mList":[{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getEntity","parameterSize":1,"parameters":[{"clazz":"java.util.List","clsList":null,"isGenericity":false,"value":""}],"returnType":"com.qa.scftemplate.entity.Entity","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getMapEntity","parameterSize":2,"parameters":[{"clazz":"java.util.Map","clsList":null,"isGenericity":false,"value":""},{"clazz":"int","clsList":null,"isGenericity":false,"value":""}],"returnType":"java.lang.String","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getTextString","parameterSize":2,"parameters":[{"clazz":"java.util.List","clsList":null,"isGenericity":false,"value":""},{"clazz":"java.lang.String","clsList":null,"isGenericity":false,"value":""}],"returnType":"java.lang.String","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getArrayInt","parameterSize":1,"parameters":[{"clazz":"[I","clsList":null,"isGenericity":false,"value":""}],"returnType":"[I","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getArrayInt","parameterSize":1,"parameters":[{"clazz":"[Ljava.lang.Integer;","clsList":null,"isGenericity":false,"value":""}],"returnType":"[Ljava.lang.Integer;","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getSetEntity","parameterSize":2,"parameters":[{"clazz":"java.util.Set","clsList":null,"isGenericity":false,"value":""},{"clazz":"int","clsList":null,"isGenericity":false,"value":""}],"returnType":"java.lang.String","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"returnJsonString","parameterSize":1,"parameters":[{"clazz":"com.qa.scftemplate.entity.Entity","clsList":null,"isGenericity":false,"value":""}],"returnType":"java.lang.String","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getEntityString","parameterSize":1,"parameters":[{"clazz":"java.util.List","clsList":null,"isGenericity":false,"value":""}],"returnType":"java.lang.String","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getArrayEntity","parameterSize":2,"parameters":[{"clazz":"[Lcom.qa.scftemplate.entity.Entity;","clsList":null,"isGenericity":false,"value":""},{"clazz":"int","clsList":null,"isGenericity":false,"value":""}],"returnType":"[Lcom.qa.scftemplate.entity.Entity;","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getArrayString","parameterSize":1,"parameters":[{"clazz":"[Ljava.lang.String;","clsList":null,"isGenericity":false,"value":""}],"returnType":"[Ljava.lang.String;","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"},{"className":"com.qa.scftemplate.contract.ISCFServiceForDyjAction","methodName":"getArrayPrimative","parameterSize":7,"parameters":[{"clazz":"[I","clsList":null,"isGenericity":false,"value":""},{"clazz":"[F","clsList":null,"isGenericity":false,"value":""},{"clazz":"[S","clsList":null,"isGenericity":false,"value":""},{"clazz":"[D","clsList":null,"isGenericity":false,"value":""},{"clazz":"[J","clsList":null,"isGenericity":false,"value":""},{"clazz":"[B","clsList":null,"isGenericity":false,"value":""},{"clazz":"[C","clsList":null,"isGenericity":false,"value":""}],"returnType":"[Ljava.lang.String;","url":"tcp://SCFServiceForDyj/SCFServiceForDyjActionService"}]} 请问是不是fastJson中的bug或是我反序列化时需要加什么参数?