fastjson 转换出现错误:json中有该属性的值,但是转换为对象后该属性的值为null

们会 发布于 04/06 09:55
阅读 628
收藏 0

【Gopher China万字分享】华为云的Go语言云原生实战经验!>>>

当我使用 netty 从客户端向服务端发送请求的时候,在客户端发出的消息的打印与服务端接受的消息的打印是一样,但是当我使用 JSON.parseObject(msg.toString(),Request.class) 转换出的 Request 对象其中的属性值却为 null,相关代码如下:

// 客户端发送消息
public SynchronousQueue<Object> sendRequest(Request request,Channel channel) {
    SynchronousQueue<Object> queue = new SynchronousQueue<>();
    queueMap.put(request.getId(), queue);
    System.out.println(request);
    channel.writeAndFlush(request);
    return queue;
}

客户端控制台的打印,出问题的是画红框的部分:

// 服务端接收消息
public void channelRead(ChannelHandlerContext ctx, Object msg)   {
    System.out.println(msg.toString());
    Request request = JSON.parseObject(msg.toString(),Request.class);
    System.out.println(request);
    if ("heartBeat".equals(request.getMethodName())) {
        logger.info("客户端心跳信息..."+ctx.channel().remoteAddress());
    }else{
        logger.info("RPC客户端请求接口:"+request.getClassName()+"   方法名:"+request.getMethodName());
        Response response = new Response();
        response.setRequestId(request.getId());
        try {
            Object result = this.handler(request);
            response.setData(result);
        } catch (Throwable e) {
            e.printStackTrace();
            response.setCode(1);
            response.setError_msg(e.toString());
            logger.error("RPC Server handle request error",e);
        }
        ctx.writeAndFlush(response);
    }
}

服务端控制台打印:

服务端与客户端公有的 Request 实体类:

public class Request implements Serializable {
    private String id;
    private String className;// 类名
    private String methodName;// 函数名称
    private Class<?>[] parameterTypes;// 参数类型
    private Object[] parameters;// 参数列表
    // 省略 get、set、toString 方法
}

如图所示,当我从客户端向服务端传送 json 格式的数据的时候,服务端接受到的 msg 与客户端的数据一样,但是在使用 fastjson 将 json 转换为对象时,原 json 的 "parameterTypes":["cn.lk.netty.rpc.consumer.bean.InfoUser"] 在对象中却显示为 parameterTypes=[null]。请问这是为什么,有没有可能是因为泛型擦除,以及有什么解决办法。

希望路过的大佬帮帮忙,我在这里跪谢了!!!

加载中
1
ZhangLi2
ZhangLi2

建议放弃fastjson,漏洞实在太多。已经有相当多的公司禁止在项目中使用fastjson了

们会
们会
如果解决不了的话就打算换别的了,比如 gson
0
kakai
kakai

你本地是否有“ cn.lk.netty.rpc.consumer.bean.InfoUser ”这个类?单独测试字符串和class的转换是没任何问题的,感觉还是你的代码有问题。

们会
们会
回复 @kakai : json补充在问答了,此外对于 parameterTypes 属性,当我将它的类型由 Class<?>[] 修改为 String[] 的时候是可以正常打印的。我觉得是泛型的问题。目前在解决
kakai
kakai
回复 @们会 : 你可以把那段json字符串拿出来单独与Request进行反序列化,或者你可以把那段json发上来一起参考。
们会
们会
在生产者和消费者都有这个 InfoUser 实体类,并且路径都是对的。在网上找不到相关的问题,我也觉得大概率是我代码的问题,但是具体的想不出来。
0
们会
们会

补充一下,第二张图的数据分别是

msg 数据: {"parameterTypes":["cn.lk.netty.rpc.consumer.bean.InfoUser"],"methodName":"insertInfoUser","className":"cn.lk.netty.rpc.service.InfoUserService","id":"7935386766086250497","parameters":[{"address":"BeiJing","name":"Jeen","id":"7935386766086250496"}]}

request 数据:Request{id='7935386766086250497', className='cn.lk.netty.rpc.service.InfoUserService', methodName='insertInfoUser', parameterTypes=[null], parameters=[{"address":"BeiJing","name":"Jeen","id":"7935386766086250496"}]}

0
们会
们会

做了个折中办法,在生产者的 request 中添加一个  rparameterTypes 用于存储原来的  parameterTypes ,原来的  parameterTypes  修改为 String[]——用于存储类名,然后用 Class.forName(str) 方法加载到 rparameterTypes。解决了。

0
kakai
kakai

我把你的msg作为json字符串测试了,仅仅是把你的 parameterTypes  转为我这边自己的类完全限定名,一切正常。

public class TestJson {

    public static void main(String[] args) {
        String str = "{\"parameterTypes\":[\"ls.ddz.db.model.UserInfo\"]," +
                "\"methodName\":\"insertInfoUser\",\"className\":\"cn.lk.netty.rpc.service.InfoUserService\"," +
                "\"id\":\"7935386766086250497\",\"parameters\":[{\"address\":\"BeiJing\",\"name\":\"Jeen\"," +
                "\"id\":\"7935386766086250496\"}]}";
        Request request = JSON.parseObject(str, Request.class);
        System.out.println(Arrays.toString(request.getParameterTypes()));
    }

}

 

 

们会
们会
回复 @kakai : 能看下你的测试代码吗?我的测试代码发上去了,看下哪里和你的不一样。另外你用的 fastjson 版本是多少
kakai
kakai
回复 @们会 : 我的就是Class<?>,不是String
们会
们会
之前我的 Request.parameterTypes 类型是 Class<?>[],并不是 String[]。如果类型为 Class<?>[] 的话获取的是 null,String[] 才能获取到值。
0
们会
们会

以下是我的测试代码:

public class TestJson {

    public static void main(String[] args) {
        String str = "{\"parameterTypes\":[\"ls.ddz.db.model.UserInfo\"]," +
                "\"methodName\":\"insertInfoUser\",\"className\":\"cn.lk.netty.rpc.service.InfoUserService\"," +
                "\"id\":\"7935386766086250497\",\"parameters\":[{\"address\":\"BeiJing\",\"name\":\"Jeen\"," +
                "\"id\":\"7935386766086250496\"}]}";
        String str2 = "{\"parameterTypes\":[\"cn.lk.netty.rpc.consumer.bean.InfoUser\"],\"methodName\":\"insertInfoUser\",\"className\":\"cn.lk.netty.rpc.service.InfoUserService\",\"id\":\"7935386766086250497\",\"parameters\":[{\"address\":\"BeiJing\",\"name\":\"Jeen\",\"id\":\"7935386766086250496\"}]}";
        Request request = JSON.parseObject(str, Request.class);
        Request2 request2 = JSON.parseObject(str2, Request2.class);
        System.out.println(request);
        System.out.println(request2);
    }

}

class Request2 {
    private String id;
    private String className;// 类名
    private String methodName;// 函数名称
    private Class<?>[] parameterTypes;// 参数类型
    private Object[] parameters;// 参数列表

    public String getId() {
        return id;
    }

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

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public Class<?>[] getParameterTypes() {
        return parameterTypes;
    }

    public void setParameterTypes(Class<?>[] parameterTypes) {
        this.parameterTypes = parameterTypes;
    }

    public Object[] getParameters() {
        return parameters;
    }

    public void setParameters(Object[] parameters) {
        this.parameters = parameters;
    }

    @Override
    public String toString() {
        return "Request2{" +
                "id='" + id + '\'' +
                ", className='" + className + '\'' +
                ", methodName='" + methodName + '\'' +
                ", parameterTypes=" + Arrays.toString(parameterTypes) +
                ", parameters=" + Arrays.toString(parameters) +
                '}';
    }
}

public class Request {
    private String id;
    private String className;// 类名
    private String methodName;// 函数名称
    private String[] parameterTypes; // 参数类型 string表示
    private Class<?>[] rparameterTypes;// 参数类型
    private Object[] parameters;// 参数列表
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
    public String getMethodName() {
        return methodName;
    }
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public String[] getParameterTypes() {
        return parameterTypes;
    }

    public void setParameterTypes(String[] parameterTypes) {
        this.parameterTypes = parameterTypes;
    }

    public Class<?>[] getRparameterTypes() {
        return rparameterTypes;
    }

    public void setRparameterTypes(Class<?>[] rparameterTypes) {
        this.rparameterTypes = rparameterTypes;
    }

    public Object[] getParameters() {
        return parameters;
    }
    public void setParameters(Object[] parameters) {
        this.parameters = parameters;
    }

    @Override
    public String toString() {
        return "Request{" +
                "id='" + id + '\'' +
                ", className='" + className + '\'' +
                ", methodName='" + methodName + '\'' +
                ", parameterTypes=" + Arrays.toString(parameterTypes) +
                ", rparameterTypes=" + Arrays.toString(rparameterTypes) +
                ", parameters=" + Arrays.toString(parameters) +
                '}';
    }
}

pom.xml 引用:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>
0
kakai
kakai
import java.io.Serializable;

public class Request implements Serializable {
    private String id;
    private String className;// 类名
    private String methodName;// 函数名称
    private Class<?>[] parameterTypes;// 参数类型
    private Object[] parameters;// 参数列表

    public String getId() {
        return id;
    }

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

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public Class<?>[] getParameterTypes() {
        return parameterTypes;
    }

    public void setParameterTypes(Class<?>[] parameterTypes) {
        this.parameterTypes = parameterTypes;
    }

    public Object[] getParameters() {
        return parameters;
    }

    public void setParameters(Object[] parameters) {
        this.parameters = parameters;
    }
}
import com.alibaba.fastjson.JSON;

import java.util.Arrays;

public class TestJson {

    public static void main(String[] args) {
        String str = "{\"parameterTypes\":[\"ls.ddz.db.model.UserInfo\"]," +
                "\"methodName\":\"insertInfoUser\",\"className\":\"cn.lk.netty.rpc.service.InfoUserService\"," +
                "\"id\":\"7935386766086250497\",\"parameters\":[{\"address\":\"BeiJing\",\"name\":\"Jeen\"," +
                "\"id\":\"7935386766086250496\"}]}";
        Request request = JSON.parseObject(str, Request.class);
        System.out.println(Arrays.toString(request.getParameterTypes()));
    }

}
<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.68</version>
        </dependency>

 

kakai
kakai
ls.ddz.db.model.UserInfo是我这边的类,你需要换成你那边的
0
kakai
kakai

1.2.62的版本我也试过了,没问题

kakai
kakai
回复 @们会 : 你换成这个试试? parameterTypes你用java.util.ArrayList试试?
kakai
kakai
回复 @们会 : parameterTypes你用的什么?
们会
们会
回复 @kakai : 我将你的代码复制粘贴到了我的上面,同时 fastjson 的版本也换成了 1.2.68,可打印出来的还是 null。
kakai
kakai
回复 @们会 : parameterTypes这个你随便换一个试试?
kakai
kakai
回复 @们会 : 奇怪了,我用的8
下一页
0
们会
们会

这个是我按照你的代码改的,但是输出也还是 null。

返回顶部
顶部