Fastjson与Gson的简单使用

Fastjson

Java对象 -> Json字符串

Fastjson将对象转成Json字符串依赖于对象的get方法,以Person类为例(注意该类中没有sex属性的setget方法,且多加一个非本类属性的getOther方法):

public class Person {
    String name;
    Integer age;
    Integer sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getOther() {
        return "测试";
    }

    public Person(String name, Integer age, Integer sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

测试方法:

@Test
void test1() {
    Person person = new Person("coderzpw", 22, 1);
    String jsonString = JSONObject.toJSONString(person);
    System.out.println(jsonString);
}

输出结果:

在这里插入图片描述
从结果可以看出,fastjsontoJSONString方法依赖于类的get方法,而不依赖于类属性

Json字符串 -> Java对象

若存在有参构造方法,则依赖于有参构造;若无有参构造,则依赖于set方法。

存在有参构造,则依赖于有参构造

public class Person {
    String name;
    Integer age;
    Integer sex;

    public Person(String name, Integer age, Integer sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

测试方法:

@Test
void test2() {
    String jsonStr = "{\"age\":22,\"name\":\"coderzpw\",\"sex\":\"1\"}";
    Person person = JSONObject.parseObject(jsonStr, Person.class);
    System.out.println(person);
}

输出结果:
在这里插入图片描述

不存在有参构造,则依赖于set方法

如下缺少sex属性的set方法

public class Person {
    String name;
    Integer age;
    Integer sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

测试方法:

@Test
void test2() {
    String jsonStr = "{\"age\":22,\"name\":\"coderzpw\",\"sex\":\"1\"}";
    Person person = JSONObject.parseObject(jsonStr, Person.class);
    System.out.println(person);
}

输出结果:

在这里插入图片描述

Json字符串 -> JSONObject对象

还是之前的JSONObject.parseObject方法,只是这次参数只需要一个json字符串即可,不需要xxx.class

@Test
void test3() {
    String jsonStr = "{\"age\":22,\"name\":\"coderzpw\",\"sex\":\"1\"}";
    JSONObject jsonObject = JSONObject.parseObject(jsonStr);
    System.out.println(jsonObject);
}

具体怎么操作 JSONObject对象可以看这篇文章:【fastjson对json对象的操作】

Json字符串 <-> JSONArray对象

对象集合转成 json字符串

@Test
void test1() {
    Person p1 = new Person("成神苦练元歌", 18, 1);
    Person p2 = new Person("小虎牙", 19, 1);
    Person p3 = new Person("国服第一JAVA", 20, 1);
    Person p4 = new Person("coderzpw", 22, 1);
    List<Person> list = new ArrayList<>();
    list.add(p1);
    list.add(p2);
    list.add(p3);
    list.add(p4);
    String jsonString = JSONObject.toJSONString(list);
    System.out.println(jsonString);
}

输出结果:

在这里插入图片描述

json字符串转成对象集合

@Test
void test4() {
    String str = "[{\"age\":18,\"name\":\"成神苦练元歌\",\"sex\":1},{\"age\":19,\"name\":\"小虎牙\",\"sex\":1},{\"age\":20,\"name\":\"国服第一JAVA\",\"sex\":1},{\"age\":22,\"name\":\"coderzpw\",\"sex\":1}]";
    // 不指定转成什么类, 最终类型是 JSONArray
    JSONArray objects = JSONObject.parseArray(str);
    System.out.println(objects);
    // 指定xxx.class,最终转成 List<Xxx>
    List<Person> persons = JSONObject.parseArray(str, Person.class);
    System.out.println(persons);
}

输出结果:

在这里插入图片描述

FastJson序列化时"$ref":“$.a.b” ——引用类型

出现$ref的原因是多个key映射同一个引用对象

以下面这个Person类为例:
这里加了Lombok的注解,已实现set、get和构造方法

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    String name;
    Integer age;
    Integer sex;
    Animal animal1;
    Animal animal2;
    Person person;
}
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Animal {
    public String name;
}

测试方法:

@Test
void test1() {
    Person person = new Person();
    person.setName("coderzpw");
    person.setAge(22);
    person.setSex(1);
    Animal animal = new Animal("哈士奇");
    // 这里 animal1 和 animal2 指定同一个引用对象 animal
    person.setAnimal1(animal);   
    person.setAnimal2(animal);
    // person对象指向自己(直接调用JSONObject.toJSON,会出现循环引用导致占内存溢出)
    person.setPerson(person);   
    String jsonString = JSONObject.toJSONString(person);
    System.out.println(jsonString);

}

输出结果:

在这里插入图片描述
因为循环引用的会问题,这里如果想要直接通过 (JSONObject)JSONObject.toJSON(person)将person对象直接转成JSONObject,则会报栈内存溢出错误

@Test
void test1() {
    Person person = new Person();
    person.setName("coderzpw");
    person.setAge(22);
    person.setSex(1);
    Animal animal = new Animal("哈士奇");
    // 这里 animal1 和 animal2 指定同一个引用对象 animal
    person.setAnimal1(animal);
    person.setAnimal2(animal);
    // person对象指向自己(直接调用JSONObject.toJSON,会出现循环引用导致占内存溢出)
    person.setPerson(person);
    JSONObject jsonObject = (JSONObject)JSONObject.toJSON(person);
    System.out.println(jsonObject);

}

输出结果:

在这里插入图片描述

解决方案:JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(person))先转成字符串,再转成JSONObject

@Test
void test1() {
    Person person = new Person();
    person.setName("coderzpw");
    person.setAge(22);
    person.setSex(1);
    Animal animal = new Animal("哈士奇");
    person.setAnimal1(animal);
    person.setAnimal2(animal);
    person.setPerson(person);
    JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(person));
    System.out.println(jsonObject);
    System.out.println(jsonObject.get("animal2"));
    System.out.println(jsonObject.get("person"));
}

输出结果:

在这里插入图片描述

常见引用符文含义

“$ref”:”..” 上一级
“$ref”:”@” 当前对象,也就是自引用
“$ref”:”$” 根对象
{"$ref":"../.."} 引用父对象的父对象
“$ref”:”$.children.0” 基于路径的引用,相当于root.getChildren().get(0)

Gson

Java对象 -> Json字符串

Gson将对象转成Json字符串依赖于对象的属性(不依赖get方法),以Person类为例:

public class Person {
    String name;
    Integer age;
    Integer sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getOther() {
        return "测试";
    }

    public Person(String name, Integer age, Integer sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                '}';
    }
}

Java对象转Json字符串:

测试方法:

@Test
void test2() {
    Person person = new Person("coderzpw", 22, 1);
    Gson gson = new Gson();
    String jsonStr = gson.toJson(person);
    System.out.println(jsonStr);
}

结果输出:

在这里插入图片描述

Java对象集合转Json字符串:

测试代码:

@Test
void test2() {
    Person p1 = new Person("成神苦练元歌", 18, 1);
    Person p2 = new Person("小虎牙", 19, 1);
    Person p3 = new Person("国服第一JAVA", 20, 1);
    Person p4 = new Person("coderzpw", 22, 1);
    List<Person> list = new ArrayList<>();
    list.add(p1);
    list.add(p2);
    list.add(p3);
    list.add(p4);
    Gson gson = new Gson();
    String jsonStr = gson.toJson(list);
    System.out.println(jsonStr);
}

输出结果:

在这里插入图片描述

Java的Map转成Json字符串:

测试方法:

@Test
void test2() {
    Map<String, Person> map = new HashMap<>();
    Person p1 = new Person("成神苦练元歌", 18, 1);
    Person p2 = new Person("小虎牙", 19, 1);
    Person p3 = new Person("国服第一JAVA", 20, 1);
    Person p4 = new Person("coderzpw", 22, 1);
    map.put("p1", p1); map.put("p2", p2); map.put("p3", p3); map.put("p4", p4);
    Gson gson = new Gson();
    String jsonStr = gson.toJson(map);
    System.out.println(jsonStr);
}

测试方法:

在这里插入图片描述

Json字符串 -> Java对象

测试方法:

@Test
void test2() {
    String jsonStr = "{\"name\":\"成神苦练元歌\",\"age\":18,\"sex\":1}";
    Gson gson = new Gson();
    Person person = gson.fromJson(jsonStr, Person.class);
    System.out.println(person);
}

输出结果:

在这里插入图片描述

Json字符串 -> List 和 Map

对于ListSetMap这些类型,不能直接使用formJson(jsonStr, xxx.class),否则会转成Object
可以统一写成gson.fromJson(jsonStr, new TypeToken<xxx>() {}.getType())的格式, 其中xxx用来指定集合类型。

Json字符串转成List

测试方法:

@Test
void test2() {
    String jsonStr = "[{\"name\":\"成神苦练元歌\",\"age\":18,\"sex\":1},{\"name\":\"小虎牙\",\"age\":19,\"sex\":1},{\"name\":\"国服第一JAVA\",\"age\":20,\"sex\":1},{\"name\":\"coderzpw\",\"age\":22,\"sex\":1}]";
    Gson gson = new Gson();
    List<Person> list = gson.fromJson(jsonStr, new TypeToken<List<Person>>() {}.getType());
    System.out.println(list);
}

输出结果:

在这里插入图片描述

Json字符串转成Map

测试方法:

@Test
void test2() {
    String jsonStr = "{\"p1\":{\"name\":\"成神苦练元歌\",\"age\":18,\"sex\":1},\"p2\":{\"name\":\"小虎牙\",\"age\":19,\"sex\":1},\"p3\":{\"name\":\"国服第一JAVA\",\"age\":20,\"sex\":1},\"p4\":{\"name\":\"coderzpw\",\"age\":22,\"sex\":1}}";
    Gson gson = new Gson();
    Map<String, Person> map = gson.fromJson(jsonStr, new TypeToken<Map<String, Person>>() {}.getType());
    System.out.println(map);
}

输出结果:

在这里插入图片描述