https://github.com/mbechler/marshalsec
fastjson反序列化
fastjson三种反序列化方式的差异
参考:
https://xz.aliyun.com/t/7027
1、返回结果的对象类型不同
说明:
使用
JSON.parse(serializedStr);
或者
JSON.parseObject(serializedStr); // 不指定具体类
得到的对象为com.alibaba.fastjson.JSONObject
类型,也就是json字符串。
使用
JSON.parseObject(serializedStr,User.class); // 指定具体类,这里为com.cqq.User类
得到的对象类型为com.cqq.User
。
PS:查看JSON.parseObject
的具体实现,发现其实最终还是调用了JSON.parse
。
//TODO 后续再深入
2、执行过程中调用的方法不同
使用FastJsonTest
进行测试,发现在反序列化中调用的方法不同。
发现这三种方式都会调用目标类的set方法,但是只有
JSON.parseObject(payload);
会调用目标类的get方法。
调用栈如下:
就是因为parseObject比其他方式多了一个toJSON操作。因为要得到json数据,就得调用目标类的get方法,拿到这个对象的某个属性值。
@type字段的使用
其实就是JSON.toJSONString
方法多加一个参数。之前是:
String serializedStr = JSON.toJSONString(user1);
现在改成
String serializedStr = JSON.toJSONString(user1, SerializerFeature.WriteClassName);
使用Person类进行反序列化实验
测试代码如下:
package com.cqq;
import com.alibaba.fastjson.JSON;
public class Type {
public static void main(String[] args) {
String eneity3 = "{\"@type\":\"com.cqq.Person\", " +
"\"name\":\"cqq\", \"full_name\":\"caiqiqi\", " +
"\"age\": 18, \"prop\": {\"123\":123}, \"sex\": 1}";
//反序列化
Object obj = JSON.parseObject(eneity3, Person.class);
//输出会调用obj对象的toString函数
System.out.println(obj);
}
}
Person类内容如下:
package com.cqq;
import java.util.Properties;
public class Person {
//属性
public String name;
private String full_name;
private int age;
private Boolean sex;
private Properties prop;
//构造函数
public Person(){
System.out.println("[*] Person构造函数");
}
//set
public void setAge(int age){
System.out.println("[*] setAge()");
this.age = age;
}
//get 返回Boolean
public Boolean getSex(){
System.out.println("[*] getSex()");
return this.sex;
}
//get 返回ProPerties
public Properties getProp(){
System.out.println("[*] getProp()");
return this.prop;
}
//在输出时会自动调用的对象ToString函数
public String toString() {
String s = "[Person Object] name=" + this.name
+ " full_name=" + this.full_name + ", age=" + this.age
+ ", prop=" + this.prop + ", sex=" + this.sex;
return s;
}
}
从结果看,发现只有name和age被解析出来了。猜想分析:
1、对比name和full_name,他们的值在json数据中都指定了,而且Person类中都没有他们的set和get方法,但是name属性是public的,而full_name属性是private的。
2、age内容被输出,发现setAge()被调用了。
3、虽然getProp()方法也被调用了,但是由于prop属性是private的,且没有相应的set方法,无法将json字符串中的值赋值给对象。
然而并不是这样。