JSON.parseObject()不能转换父类属性

4,481 阅读2分钟

先介绍一下业务场景,现在有一个业务对象基类:

public class JsonRequest{
    private String msg;
    private String code;
}

现在有N多子类对其进行继承,并且自带一个业务对象

public class DetailJsonRequest extends JsonRequest{
    private T body;
}

想这样的一个对象,可能被用于序列号传输对象,在微服务中可能被用到

那么现在,我作为业务受理方,需要接受消费方发送来的请求,一般通过验签解密之后,会获取到一个字符串,我们这里假设序列化方式为Json

那么解析以后,我获取到这么一个字符串:

    String content = "{\"body\":{\"id\":\"1123\",\"name\":\"macky\"},\"code\":\"1\",\"msg\":\"成功\"}";

接下来,根据我需要的业务类型,进行转换:

  • 方式1:
DetailJsonRequest jsonObject = JSON.parseObject(content, DetailJsonRequest.class);
  • 方式2:
DetailJsonRequest jsonObject = JSON.parseObject(content, new TypeReference<DetailJsonRequest<JsonContent>>(JsonContent.class) {});

接下来,让我们看看效果:

  • 方式1结果:
DetailJsonRequest(body={"name":"macky","id":"1123"})
  • 方式2结果:
DetailJsonRequest(body=JsonContent(id=1123, name=macky))

发现了啥猫腻了吗,这里丢失了msg和code信息,大惊失色!!

经过各种查找,通过文档、github issue等等等,发现了罪魁祸首——toString方法

我在平常工作中,会使用到lombok插件,然后会数据打上@data注解,轻松完成一个bean构造

所以上述的JsonRequest和DetailJsonRequest都挂着@data注解

现在,给DetailJsonRequest加上另一个注解:@ToString(callSuper=true)

或者是如果你没有使用lombok,那么使用这样一个toString方法:

    @Override
    public String toString() {
        return "DetailJsonRequest{" +
                "body=" + body +
                ", msg='" + super.getMsg() + '\'' +
                ", code='" + super.getCode() + '\'' +
                '}';
    }

重新验证,会发现俩个方式的解析都可以得到msg和code信息:

DetailJsonRequest(super=JsonRequest(msg=成功, code=1), body={"name":"macky","id":"1123"})
DetailJsonRequest(super=JsonRequest(msg=成功, code=1), body=JsonContent(id=1123, name=macky))

问题解决了,那么现在回过头来看看,为何这样做是可以的,知其然,知其所以然

……未完待续

如若有错,烦请指出