1. Gson是什么(What is Gson)
Gson是一个开源的Java库,用于任意Java对象与JSON之间的相互转换,由Google开发维护。
Gson的优势:
- 简单易用:以
toJson
和fromJson
两个方法为核心 - 不需要annotations的支持,可以在缺少源代码或不方便修改源代码的情况下使用
- 支持泛型和集合
github:
API Spec:2. 将Gson引入项目
- 在Maven中加入依赖:
com.google.code.gson gson 2.5
- 将jar直接加入项目的lib文件夹
为了图省事,我把相应jar放在我的。(其实是把maven下载的版本打包而已)
3. 示例(How to use)
3.1 --自定义测试类--
public class Person implements Serializable, Comparable{ private static final long serialVersionUID = 2373954257153196535L; private String name; private int age; private String gender; //实现Comparable只是为了测试Set的序列化/反序列化,并无其他意思 public int compareTo(Person o) { if(o == null) return -1; if(this == o) return 0; if(this.getName().equals(o.getName()) && this.getAge() == o.getAge() && this.getGender() == o.getGender()) return 0; return -1; } // a series of setter/getter}
3.2 序列化
Java对象 → JSON:toJson(Object)
Person p1 = new Person("David", 26, "male");Person p2 = new Person("Annie", 23, "female");Person p3 = new Person("琼恩", 29, "男");Gson gson = new Gson();//也可以通过new GsonBuilder().create();来实例化//单个对象String json = gson.toJson(p1);//{"name":"David","age":26,"gender":"male"}//ListListlist = Arrays.asList(p1, p2, p3);String jsonList = gson.toJson(list);//SetSet set = new HashSet ();set.add(p1);set.add(p2);set.add(p1);String jsonSet = gson.toJson(set);//数组:先转换成ListPerson[] arr = {p1, p2, p3};List jsonArrList = Arrays.asList(arr);String jsonArr = gson.toJson(jsonArrList);/* * 关于Java关键字:transient * * transient声明的field(成员变量)在对象序列化时会被忽略, * 常用于声明password之类比较敏感的变量。 * transient不能用于声明方法。(反正方法既不会也没必要被序列化) * * 由于gson.toJson(obj)涉及序列化,transient在此也会生效, * 即transient声明的变量不会出现在生成的json(String)中。(亲测) */
3.3 反序列化
JSON → Java对象:fromJson(String, Type)
- 反序列化时,必须提供反序列化的类型
java.lang.reflect.Type
- 对于普通的引用类型(Object子类),可使用
java.lang.Class
对象(实现了Type接口)
Type t1 = Person.class;Type t2 = p1.getClass();boolean flag = (t1 == t2);//truePerson person = gson.fromJson(json, t1);System.out.println(person.getName());//David
- 对于参数化类型(即泛型),可通过
com.google.gson.reflect.TypeToken
获取其类型
Type setType = new TypeToken>(){}.getType();//TypeToken 的Constructor(构造器/构造方法)为protected, 使用匿名内部类的方式进行实例化Set people = gson.fromJson(jsonSet, setType);Iterator ps = people.iterator();while(ps.hasNext()){ System.out.println(ps.next().getName());}
3.4 重定向数据来源/输出
默认情况下,toJson(Object)
将生成的JSON数据保存在一个StringWriter
中;fromJson(String, Type)
则是从String中读取。可传入相应Writer
或Reader
改变数据的去处或来源。
File f = new File("/Users/Lawrence/Documents/out.txt");Writer out = new FileWriter(f);gson.toJson(set, out);//将生成的JSON数据保存在文件中,而不是默认的Stringout.close();Reader reader = new FileReader(f);SetsetFromFile = gson.fromJson(reader, setType);//从文件中读取数据,而不是默认的StringSystem.out.println(setFromFile.size());//2reader.close();/* * 改变数据输出,需要java.lang.Appendable * 事实上Writer就实现了Appendable,所以其子类都满足这个条件 */
3.5 --修改自定义测试类--
Person类增加两个变量:
- geo:长度为2的double数组用于表示地理位置,即经纬度
- Account
public class Person implements Serializable, Comparable{ private static final long serialVersionUID = 2373954257153196535L; private String name; private int age; private String gender; private double[] geo = new double[2]; private Account account; /* a series of setter/getter */}
Account.java:
public class Account { private String id; private String email; private Date dateOfRegister = new Date(); /* setter/getter */}
3.6 自定义输出格式
通过修改GsonBuilder的属性,自定义输出的结果:
Person p1 = new Person("David", 26, "male");Account ac = new Account("id", "test1@test1.com
");p1.setAccount(ac);Person p2 = new Person("Rose", 23, "女");Account ac2 = new Account("id2", "test2@test2.com
");p2.setAccount(ac2);Person p3 = new Person();p3.setName("Hello");Listlist = Arrays.asList(p1, p2, p3);Gson gson = new GsonBuilder() .setPrettyPrinting()//自动换行和添加缩进 .serializeNulls()//保留null的变量并将值设为null .disableHtmlEscaping()//不会对用于表示HTML标签的"<"和">"编码 .setDateFormat("yyyy-MM-dd")//为所有java.util.Date定义输出格式 .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES) //定义变量名的显示方式,如此处将Account的dateOfRegister定义输出为"Date Of Register" .create();System.out.println(gson.toJson(list));
以上输出为
[ { "Name": "David", "Age": 26, "Gender": "male", "Geo": [ 0.0, 0.0 ], "Account": { "Id": "id", "Email": "test1@test1.com
", "Date Of Register": "2015-12-16" } }, { "Name": "Rose", "Age": 23, "Gender": "女", "Geo": [ 0.0, 0.0 ], "Account": { "Id": "id2", "Email": "test2@test2.com
", "Date Of Register": "2015-12-16" } }, { "Name": "Hello", "Age": 0, "Gender": null, "Geo": [ 0.0, 0.0 ], "Account": null }]
3.7 操作JSON树
将3.6中添加的由3个Person对象组成的list为例:
JsonElement root = gson.toJsonTree(list);//3个Person对象if(root.isJsonArray()){ JsonArray arr = (JsonArray) root; Iteratoriter = arr.iterator(); JsonElement target = null; while(iter.hasNext()){ JsonObject element = (JsonObject) iter.next(); String name = element.get("Name").getAsString(); if("Hello".equals(name)){// arr.remove(element);//不能调用ArrayList的remove(), 因为会抛出java.util.ConcurrentModificationException iter.remove();//需要调用的是Iterator的remove(); } }}System.out.println(gson.toJson(root));
4. 说明
以上内容均参考官方文档,如有错误,还望指正。
- github:
- API Spec: