FastJson介绍&入门

FastJson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到Java Bean

序列化

序列化的函数为JSON.toJSONString

User.java

import java.util.Properties;

public class User {
    public String name1; //public且有get set
    public String name2; //public且有get
    public String name3; //public且有set
    public String name4; //仅仅public

    private String age1; //private且有get set
    private String age2; //private且有get
    private String age3; //private且有set
    private String age4; //仅仅private

    public Properties prop1_1;   //public且有get set
    public Properties prop1_2;   //public且有get
    public Properties prop1_3;   //public且有set
    public Properties prop1_4;   //仅仅public

    private Properties prop2_1;   //private且有get set
    private Properties prop2_2;   //private且有get
    private Properties prop2_3;   //private且有set
    private Properties prop2_4;   //仅仅private

    @Override
    public String toString() {
        return "User{" +
                "name1='" + name1 + '\'' +
                ", name2='" + name2 + '\'' +
                ", name3='" + name3 + '\'' +
                ", name4='" + name4 + '\'' +
                ", age1='" + age1 + '\'' +
                ", age2='" + age2 + '\'' +
                ", age3='" + age3 + '\'' +
                ", age4='" + age4 + '\'' +
                ", prop1_1=" + prop1_1 +
                ", prop1_2=" + prop1_2 +
                ", prop1_3=" + prop1_3 +
                ", prop1_4=" + prop1_4 +
                ", prop2_1=" + prop2_1 +
                ", prop2_2=" + prop2_2 +
                ", prop2_3=" + prop2_3 +
                ", prop2_4=" + prop2_4 +
                '}';
    }

    public void setProp1_3(Properties prop1_3) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        this.prop1_3 = prop1_3;
    }

    public void setProp2_3(Properties prop2_3) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        this.prop2_3 = prop2_3;
    }

    public Properties getProp1_2() {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        return prop1_2;
    }

    public Properties getProp2_2() {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        return prop2_2;
    }

    public Properties getProp1_1() {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        return prop1_1;
    }

    public void setProp1_1(Properties prop1_1) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        this.prop1_1 = prop1_1;
    }

    public Properties getProp2_1() {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        return prop2_1;
    }

    public void setProp2_1(Properties prop2_1) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        this.prop2_1 = prop2_1;
    }

    public String getName1() {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        return name1;
    }

    public void setName1(String name1) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        this.name1 = name1;
    }

    public String getAge1() {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        return age1;
    }

    public void setAge1(String age1) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        this.age1 = age1;
    }


    public String getName2() {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        return name2;
    }

    public String getAge2() {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        return age2;
    }

    public void setName3(String name3) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        this.name3 = name3;
    }

    public void setAge3(String age3) {
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        System.out.println(methodName + "() is called");
        this.age3 = age3;
    }



    public User() {
        this.name1 = "rai4over1";
        this.name2 = "rai4over2";
        this.name3 = "rai4over3";
        this.name4 = "rai4over4";

        this.age1 = "a1";
        this.age2 = "a2";
        this.age3 = "a3";
        this.age4 = "a4";

        prop1_1 = new Properties();
        prop1_2 = new Properties();
        prop1_3 = new Properties();
        prop1_4 = new Properties();

        prop1_1.put("prop1_1", "1_1");
        prop1_2.put("prop1_2", "1_2");
        prop1_3.put("prop1_3", "1_3");
        prop1_4.put("prop1_4", "1_4");


        prop2_1 = new Properties();
        prop2_2 = new Properties();
        prop2_3 = new Properties();
        prop2_4 = new Properties();

        prop2_1.put("prop2_1", "2_1");
        prop2_2.put("prop2_2", "2_2");
        prop2_3.put("prop2_3", "2_3");
        prop2_4.put("prop2_4", "2_4");

        System.out.println("User init() is called");
    }
}

该类中使用无参数构造函数初始化成员,包含16个成员,分别为StringProperties两种类型,并被publicprivate修饰的,并且对应的getset方法有所不同形成对比,以探究具体的调用情况。

非自省

常用的方式为:

public static String toJSONString(Object object)

Test.java

import com.alibaba.fastjson.JSON;

public class Test {
    public static void main(String[] args) {
        User a = new User();
        System.out.println("===========================");
        String jsonstr_a = JSON.toJSONString(a);
    }
}

运行结果:

User init() is called
===========================
getAge1() is called
getAge2() is called
getName1() is called
getName2() is called
getProp1_1() is called
getProp1_2() is called
getProp2_1() is called
getProp2_2() is called
{
    "age1": "a1",
    "age2": "a2",
    "name1": "rai4over1",
    "name2": "rai4over2",
    "name3": "rai4over3",
    "name4": "rai4over4",
    "prop1_1": {
        "prop1_1": "1_1"
    },
    "prop1_2": {
        "prop1_2": "1_2"
    },
    "prop1_3": {
        "prop1_3": "1_3"
    },
    "prop1_4": {
        "prop1_4": "1_4"
    },
    "prop2_1": {
        "prop2_1": "2_1"
    },
    "prop2_2": {
        "prop2_2": "2_2"
    }
}

可以发现在序列化时,FastJson会调用成员对应的get方法,被private修饰且没有get方法的成员不会被序列化,被public修饰的成员都会被序列化,并且序列化的结果是标准的JSON字符串。

自省

JSON标准是不支持自省的,也就是说根据JSON文本,不知道它包含的对象的类型。

FastJson支持自省,在序列化时传入类型信息SerializerFeature.WriteClassName,可以得到能表明对象类型的JSON文本。

FastJson的漏洞就是由于这个功能引起的。

使用方式

public static String toJSONString(Object object, SerializerFeature... features)

Test.java

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

public class Test {
    public static void main(String[] args) {
        User a = new User();
        System.out.println("===========================");
        String jsonstr_a = JSON.toJSONString(a, SerializerFeature.WriteClassName);
    }
}

运行结果:

User init() is called
===========================
getAge1() is called
getAge2() is called
getName1() is called
getName2() is called
getProp1_1() is called
点击收藏 | 1 关注 | 1
登录 后跟帖