fastjson JSONObject.toJavaObject(clazz)构造没有setter的Immutable clazz失败

u4dcyp6a  于 2021-11-27  发布在  Java
关注(0)|答案(6)|浏览(447)

fastjson 1.2.78
Oracle JDK 1.8.0_291

import lombok.Value;

@Value
public class SomeVO {
    Long id;
}
public class App {
    public static void main(String[] args) {
        final String txt = "{\"id\":42}";
        SomeVO a = JSON.parseObject(txt, SomeVO.class); // OK
        SomeVO b = JSON.parseObject(txt).toJavaObject(SomeVO.class); //com.alibaba.fastjson.JSONException: create instance error
        System.out.println(a);
        System.out.println(b);
    }
}
bpzcxfmw

bpzcxfmw1#

Long换成Integer就不会触发了,猜测是没走类型转化

另外JSONArray.toJavaList同样存在上述问题

mklgxw1f

mklgxw1f3#

只添加@Value注解,没有其他限制,那么类属性会被编译成final的,因此不能通过无参构造函数示例化

换成@Data没有问题

BTW: Lombok虽好,还是要多看使用文档啊

gopyfrb3

gopyfrb34#

@hulog 额,问题是不能换成@Data,手头很多POJO就是设计成Immutable的,就是不想要setter。如果打@Data就等于有一个无参构造器外加一堆setter,反序列化的时候fastjson看到无参构造器直接就先new一个,再一个个调setter注入,这个流程不走全参构造器,而且考虑了类型转换,是这样才不会触发这个bug的。打了@Value字段就是final我倒是知道,但是这个场景貌似和final关系不大。。。难道我漏掉啥细节了?

np8igboo

np8igboo5#

@cedric-sun

Soga,理解了,刚刚看了一下。应该不是你的问题

fastjson会检测可用的构造器(testcase中的只有全参构造器),事实上,也确实已经拿到了
但在JSON.parseObject(txt) 结果中,id默认被转成了Integer对象

// 找到的构造器
// 但因id为Integer类型,newInstance时传入Integer参数,导致示例化不成功
public SomeVO(Long id) {
    // omit...
}

目前,在无参构造器中的反序列化中,会对各个字段类型进行类型转换,但在非默认构造器示例化时,参数未进行类型转换

3qpi33ja

3qpi33ja6#

@hulog 是的,就是这样。不知道这块儿的类型转换,是否能复用无参场景的类型转换逻辑,如果可以的话fix起来应该不会太麻烦吧

相关问题