现象
在使用json-lib中JSONObject.toBean
将JsonObject
转化为由thrift生成的Java类时,发现得到的javabean中的数据均为空(null或者默认值)。
复现
测试代码:
pom.xml
1 |
|
定义一个thrift struct作为测试的类 student.thrift
1 | namespace java cn.keaper |
再自定义一个普通的javaBean,作对比之用Person.java
1 | public class Person { |
测试代码:
1 |
|
数据结果:
1 | {"name":"edward","age":"20"} |
我们可以看到我们自定义的javaBean使用toBean方法转换是没有问题的,但是thrift生成的java类在使用toBean方法时是不能正确获取到数据的。
问题溯源
通过单步跟踪发现:
在JSONObject.toBean方法中执行到以下代码:
1 | PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(bean, key); |
这里的执行对应了上文的日志输出,可见问题的原因是没有找到合适的set方法去对类的属性赋值。
我们来看看thrift生成的java类中setter,getter:
1 | public String getName() { |
这里可以看到其中是有set方法的。
那么为什么没找到呢?继续跟踪,中间过程略长,已略过,最后我们来到了Introspector.getTargetPropertyInfo()
1 | try { |
可见其中判断set方法的依据是参数个数为1,返回类型为void,方法名以set开头,所以回头看thrift生成的java类
1 | public Student setName(String name) { |
其中的set方法与我们自定义javaBean的set方法不同的是它返回void,而是返回对象本身,所以它不能够被识别为一个setter,所以导致最后没有序列化成功。
总结
Introspector
这个类是jdk中用来处理javaBean的类。The Introspector class provides a standard way for tools to learn about the properties, events, and methods supported by a target Java Bean.
所以其中对setter的处理是符合Java Bean规范的。json-lib中使用的是
commons-beanutils
包,这个包中使用的就是jdk中Introspector
来处理Java Bean,所以导致按照Java Bean 规范并不能正确的得到一个Java Bean。fastJson
fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。
经测试,使用fastjson的JSON.parseObject
方法是可以正确反序列化出thrift生成的JAVA类的,而且直接传入json字符串即可。