Gson是一個將Java對象轉爲JSON表示的開源類庫,由Google提供,而且也能夠講JSON字符串轉爲對應的Java對象。雖然有一些其餘的開源項目也支持將Java對象轉爲JSON,但是有些須要把Java註解加到你的代碼中,但是若是你不閱讀源代碼你是不清楚的,並且有些也不是徹底支持泛型的。而GSON在設計的時候把這兩點都考慮在內了。GSON的目的就是:java
提供簡單的toJson()和fromJson()方法將Java對象轉爲JSON, 反之亦然apache
容許已存在的沒法改變的類轉換成JSON或者是從JSON轉爲json
大量的支持了Java泛型api
容許爲對象定製表示方式數組
支持任意複雜的對象maven
最新版本是2.3,這個相應的jar包能夠從maven中央倉庫獲取,下載連接(http://search.maven.org/remotecontent?filepath=com/google/code/gson/gson/2.3/gson-2.3.jar),不過若是不是經過直接添加jar包的方式獲取的話能夠經過maven或者是gradle,若是是經過maven,須要在pom.xml文件中加上環境配置ide
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.3</version> </dependency>
若是是經過gradle那麼只須要配置gradle
'com.google.code.gson:gson:2.3'
Google json提供了兩種方式來實現,第一種就是用 com.google.gson.Gson類,建立一個這個類的實例而後經過使用方法fromJson(String json, Class<T> classOfT),classOfT 是JSON將要轉爲的java對象。第二種方式就是使用 com.google.gson.GsonBuilder 類,這個類容許設置一些特定的功能好比容許空序列化,建立一個GsonBuilder,而後設置完經過builder操做Gson類。 ui
咱們先來看下簡單的GSON使用方法,操做的對象實體是Albums.javathis
public class Albums { private String title; private String message; private String[] errors = new String[]{}; private String total; private int total_pages; private int page; private String limit; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String[] getErrors() { return errors; } public void setErrors(String[] errors) { this.errors = errors; } public String getTotal() { return total; } public void setTotal(String total) { this.total = total; } public int getTotal_pages() { return total_pages; } public void setTotal_pages(int total_pages) { this.total_pages = total_pages; } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public String getLimit() { return limit; } public void setLimit(String limit) { this.limit = limit; } }
(須要注意的是errors在爲實例化的時候已經賦值了爲空值,這個後面有用
經過GSON操做JavaToJsonAndBack.java
import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class JavaToJsonAndBack { /** * @param args */ public static void main(String[] args) { GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); // TODO Auto-generated method stub Albums albums = new Albums(); albums.setTitle("Free Music Archive - Albums"); albums.setMessage(""); albums.setTitle("11259"); albums.setTotal_pages(2252); albums.setPage(1); albums.setLimit("5"); System.out.println("Albums"); System.out.println(gson.toJson(albums)); } }
Albums {"title":"11259","message":"","errors":[],"total_pages":2252,"page":1,"limit":"5"}
咱們注意到的是errors屬性打印出來爲空可是出現了,如今咱們作個小小的改動就是將pojo中Albums中的errors初始化值刪掉而後再次運行main方法看打印出來的結果是什麼
private String[] errors; Albums {"title":"11259","message":"","total_pages":2252,"page":1,"limit":"5"}
咱們卻發現沒有errors這個屬性了這個是爲何呢,這個是由於咱們在實例化的時候沒有給errors賦初值,因此未能實現序列化因此沒有值,那麼咱們有什麼辦法能夠講errors這個屬性即便是空值也可以打印出來呢,方法是有的那就是經過GsonBuilder
來定製,咱們設置即便爲空也是序列化的.咱們將JavaToJsonAndBack.java作個簡單修改
import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class JavaToJsonAndBack { /** * @param args */ public static void main(String[] args) { GsonBuilder builder = new GsonBuilder().serializeNulls(); Gson gson = builder.create(); // TODO Auto-generated method stub Albums albums = new Albums(); albums.setTitle("Free Music Archive - Albums"); albums.setMessage(""); albums.setTitle("11259"); albums.setTotal_pages(2252); albums.setPage(1); albums.setLimit("5"); System.out.println("Albums"); System.out.println(gson.toJson(albums)); } }
打印出來的結果是
Albums {"title":"11259","message":"","errors":null,"total":null,"total_pages":2252,"page":1,"limit":"5"}
可見errors屬性出來了,打出來爲空
這個還能夠經過註解的方式實現@SerializedName
(
""
),還能夠經過制定NamingStrategy
builder.setFieldNamingStrategy(new FieldNamingStrategy() { @Override public String translateName(Field f) { if (f.getName().equals("albumId")) return "album_id"; else return f.getName(); } });
b):標記解析
經過a咱們知道了若是將一個Java對象轉爲JSON的兩種方式,下面介紹下如何解析JSON已經處理特殊的符號,儘管經過JSON構建Java對象看起來是一個很難完成的,可是若是你須要較高級別的去控制這個轉化過程的話,它仍是很強大的並且是個不錯的選擇。這個是具備咱們經過JsonReader去讀取JSON流,下面是一個舉例。ParseTokenExample.java
import java.io.IOException; import java.io.StringReader; import java.net.MalformedURLException; import java.net.URL; import org.apache.commons.io.IOUtils; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; public class ParseTokenExample{ public static void main(String[] args) throws MalformedURLException, IOException { String url = "http://freemusicarchive.org/api/get/albums.json?api_key=60BLHNQCAOUFPIBZ&limit=5"; String json = IOUtils.toString(new URL(url)); //使用reader去讀取json
JsonReader reader = new JsonReader(new StringReader(json));
//調用處理對象的方法去處理完整的json對象
handleObject(reader); }/** *處理對象,假設第一個標記是BEGIN_OBJECT,在對象內部即有多是數組也有可能不是,咱們須要處理這 *兩種狀況,須要注意peek()方法,它用於一般用於找出下個標記的類型 * @param reader * @throws IOException */
private static void handleObject(JsonReader reader) throws IOException { reader.beginObject(); while (reader.hasNext()) { JsonToken token = reader.peek(); if (token.equals(JsonToken.BEGIN_ARRAY)) handleArray(reader); else if (token.equals(JsonToken.END_ARRAY)) { reader.endObject(); return; } else handleNonArrayToken(reader, token); } } /**
*處理json數組,第一個標記是 JsonToken_BEGIN_ARRAY,數組可能包含對象或者基本原始類型 * * @param reader * @throws IOException */ public static void handleArray(JsonReader reader) throws IOException { reader.beginArray(); while (true) { JsonToken token = reader.peek(); if (token.equals(JsonToken.END_ARRAY)) { reader.endArray(); break; } else if (token.equals(JsonToken.BEGIN_OBJECT)) { handleObject(reader); } else handleNonArrayToken(reader, token); } } /** * 處理不是數組的符號標記 * * @param reader * @param token * @throws IOException */ public static void handleNonArrayToken(JsonReader reader, JsonToken token) throws IOException { if (token.equals(JsonToken.NAME)) System.out.println(reader.nextName()); else if (token.equals(JsonToken.STRING)) System.out.println(reader.nextString()); else if (token.equals(JsonToken.NUMBER)) System.out.println(reader.nextDouble()); else reader.skipValue(); } }
c):將JSON對象轉爲java對象樹
咱們能夠從一個json串來構建JsonElement(com.google.gson.JsonElement)樹,而後這個樹能夠轉爲java對象,JsonElement 含有isJsonObjec()以及isJsonNull()方法等等,這些方法能夠識別出JsonElement的類型。而後經過getAsJsonObject()和getAsJsonPrimitive()方法能夠獲取真正的java對象。舉例說明:ParseTreeExample.java
import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.apache.commons.io.IOUtils; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; public class ParseTreeExample6 { public static void main(String[] args) throws MalformedURLException, IOException { String url = "http://freemusicarchive.org/api/get/albums.json?api_key=60BLHNQCAOUFPIBZ&limit=5"; String json = IOUtils.toString(new URL(url)); JsonParser parser = new JsonParser();
//JsonElement是根節點,它多是一個對象數組爲空或者java原始類型 JsonElement element = parser.parse(json); // 使用isxxx方法來找出jsonelement的類型,在咱們的例子中咱們知道跟對象是Albums對象而且包含數組對象 if (element.isJsonObject()) { JsonObject albums = element.getAsJsonObject(); System.out.println(albums.get("title").getAsString()); JsonArray datasets = albums.getAsJsonArray("dataset"); for (int i = 0; i < datasets.size(); i++) { JsonObject dataset = datasets.get(i).getAsJsonObject(); System.out.println(dataset.get("album_title").getAsString()); } } } }
d):序列化List
Gson提供了com.google.gson.reflect.TypeToken這個類用於存儲泛型類型,舉例GenericTypesExample.java
import java.lang.reflect.Type; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; public class GenericTypesExample{ public static void main(String[] args) { Animal<dog> animal = new Animal<Dog>(); Dog dog = new Dog("I am a dog"); animal.setAnimal(dog); Gson gson = new Gson(); //定義一個類型 Type animalType = new TypeToken<Animal<Dog>>() { }.getType(); // 咱們首先將animal對象轉爲json而後從這個json讀取回來,可是咱們把json定義一個Animal類型 Animal animal1 = gson.fromJson(gson.toJson(animal, animalType), Animal.class); System.out.println(animal1.get().getClass()); Animal animal2 = gson.fromJson(gson.toJson(animal), animalType); System.out.println(animal2.get().getClass()); } }
Animal.javapublic class Animal<T> { public T animal; public void setAnimal(T animal) { this.animal = animal; } public T get() { return animal; } }
Dog.java
public class Dog { private String name; public Dog(String name) { this.name = name; } public String getName() { return name; } }
e):序列化內部類
Gson可以序列化內部類和靜態嵌套類,經過下面這個例子咱們能夠看到
1.序列化含有靜態嵌套類
2.序列化含有非靜態嵌套類
3.反序列化json到一個含有靜態非靜態內部類的類
4.序列化靜態嵌套類
5.序列化非靜態嵌套類
6.反序列化json到一個靜態嵌套類
7.反序列化json到一個非靜態嵌套類
舉例:SerializeInnerClassExample.java
import java.lang.reflect.Modifier; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import AlbumsWithInnerClass.Dataset; import AlbumsWithInnerClass.Dataset2; public class SerializeInnerClassExample { public static void main(String[] args) { // 建立一個含有靜態潛逃類和非靜態嵌套類的Albums類 AlbumsWithInnerClass albums = new AlbumsWithInnerClass(); albums.setName("SerializeInnerClass"); //建立一個dataset.由於它不是一個非靜態的嵌套類,因此咱們須要一個閉合的類型 Dataset dataset = albums.new Dataset(); dataset.setAlbum_id("1"); dataset.setAlbum_name("albums1"); // 將datasets set到 albums中去 albums.setDatasetsInner(new Dataset[] { dataset }); // 靜態的內部類可以被建立而不須要閉合的類型 Dataset2 dataset2 = new Dataset2(); dataset2.setAlbum_id("2"); dataset2.setAlbum_name("albums2"); albums.setDatasetsStatic(new Dataset2[] { dataset2 }); // 建立 GsonBuilder GsonBuilder builder = new GsonBuilder(); builder.excludeFieldsWithModifiers(Modifier.PRIVATE); Gson gson = builder.create(); String json = gson.toJson(albums); System.out.println(json); // 打印的結果爲 // {"name":"SerializeInnerClass","datasetsInner":[{"album_name":"SerializeInnerClass_albums1","album_id":"1"}], // "datasetsStatic":[{"album_name":"albums2","album_id":"2"}]} Gson gson3 = new Gson(); AlbumsWithInnerClass parsedAlbums = gson3.fromJson(json, AlbumsWithInnerClass.class); System.out.println(parsedAlbums.datasetsInner[0].album_name); System.out.println(parsedAlbums.datasetsStatic[0].album_name); Gson gson2 = new Gson(); String json2 = gson2.toJson(dataset); System.out.println(json2); //打印的結果爲 {"album_name":"SerializeInnerClass_albums1","album_id":"1"} String json3 = gson2.toJson(dataset2); System.out.println(json3); // 打印的結果爲 {"album_name":"albums2","album_id":"2"} // 從json字符串中建立一個內部類 Gson gson4 = new Gson(); Dataset parsedDataset = gson4.fromJson(json2, Dataset.class); System.out.println(parsedDataset.getClass()); // 打印結果class com.studytrails.json.gson.AlbumsWithInnerClass$Dataset System.out.println(parsedDataset.album_name); // 打印結果 SerializeInnerClass_albums1 // 從json中建立一個嵌套的靜態類 Dataset2 parsedStaticNestedClass = gson4.fromJson(json3, Dataset2.class); System.out.println(parsedStaticNestedClass.getClass()); // 打印結果 class com.studytrails.json.gson.AlbumsWithInnerClass$Dataset2 System.out.println(parsedStaticNestedClass.album_name); // 打印結果 albums2 } }
AlbumsWithInnerClass.java
public class AlbumsWithInnerClass { public String name; private String year; public Dataset[] datasetsInner; public Dataset2[] datasetsStatic; public void setDatasetsInner(Dataset[] datasetsInner) { this.datasetsInner = datasetsInner; } public void setDatasetsStatic(Dataset2[] datasetsStatic) { this.datasetsStatic = datasetsStatic; } public void setName(String name) { this.name = name; } public void setYear(String year) { this.year = year; } class Dataset { public String album_name; public String album_id; public void setAlbum_id(String album_id) { this.album_id = album_id; } public void setAlbum_name(String album_name) { this.album_name = name + "_" + album_name; } } static class Dataset2 { public String album_name; public String album_id; public void setAlbum_id(String album_id) { this.album_id = album_id; } public void setAlbum_name(String album_name) { this.album_name = album_name; } } }
f):自定義類型適配器
自定義類型適配器須要繼承com.google.gson.TypeAdapter這個抽象類,實現方法有 public abstract T read(JsonReader in) throws IOException; and public abstract void write(JsonWriter out, T value) throws IOException;你定義的適配器可以處理空值,建立適配器實例後須要在GsonBuilder裏面註冊,而後經過GsonBuilder來建立Json對象,用於序列化和反序列化操做。舉例:
DatasetTypeAdapterExample.java
import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.apache.commons.io.IOUtils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class DatasetTypeAdapterExample { public static void main(String[] args) throws MalformedURLException, IOException { String url = "http://freemusicarchive.org/api/get/albums.json?api_key=60BLHNQCAOUFPIBZ&limit=5"; String json = IOUtils.toString(new URL(url)); // 建立自定義心裏適配器而且把它註冊到 GsonBuilder Gson gson = new GsonBuilder().registerTypeAdapter(Dataset.class, new DatasetTypeAdapter()).create(); Albums albums = gson.fromJson(json, Albums.class); System.out.println(albums.getDataset()[1].getAlbum_title()); } }
DatasetTypeAdapter.java
import java.io.IOException; import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; public class DatasetTypeAdapter extends TypeAdapter<Dataset> { @Override public Dataset read(JsonReader reader) throws IOException { JsonToken token = reader.peek(); Dataset dataset = new Dataset(); if (token.equals(JsonToken.BEGIN_OBJECT)) { reader.beginObject(); while (!reader.peek().equals(JsonToken.END_OBJECT)) { if (reader.peek().equals(JsonToken.NAME)) { if (reader.nextName().equals("album_url")) dataset.setAlbum_title(reader.nextString()); else reader.skipValue(); } } reader.endObject(); } return dataset; } @Override public void write(JsonWriter out, Dataset value) throws IOException { } }
Albums.java
public class Albums { private String title; private Dataset[] dataset; public void setTitle(String title) { this.title = title; } public void setDataset(Dataset[] dataset) { this.dataset = dataset; } public String getTitle() { return title; } public Dataset[] getDataset() { return dataset; } }
g):自定義序列化器
建立一個自定義的序列化器須要實現com.studytrails.json.gson.JsonSerializer 接口,而後實現 public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context); 方法,src 是指源對象,Type 是指源對象的類型,舉例:
DogSerializer.java
import java.lang.reflect.Type; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import com.google.gson.reflect.TypeToken; public class DogSerializer implements JsonSerializer<dog> { @Override public JsonElement serialize(Dog src, Type typeOfSrc, JsonSerializationContext context) { JsonObject object = new JsonObject(); String name = src.getName().replaceAll(" ", "_"); object.addProperty("name", name); return object; } public static void main(String[] args) { Animall<Dog> animal = new Animall<Dog>(); Dog dog = new Dog("I am a dog"); animal.setAnimal(dog); Gson gson = new GsonBuilder().registerTypeAdapter(Dog.class, new DogSerializer()).setPrettyPrinting().create(); Type animalType = new TypeToken<Animal<Dog>>() { }.getType(); System.out.println(gson.toJson(animal, animalType)); } }Animal.java
public class Animal<t> { public T animal; public void setAnimal(T animal) { this.animal = animal; } public T get() { return animal; } }
Dog.java
public class Dog { private String name; public Dog(String name) { this.name = name; } public String getName() { return name; } }h):自定義反序列化器
建立一個反序列化器須要實現的方法有 public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException;舉例:
DogDeserialiser.java
import java.lang.reflect.Type; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; public class DogDeserialiser implements JsonDeserializer<Dog> { @Override public Dog deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String name = json.getAsJsonObject().get("name").getAsString(); name = name.replace(" ", "_"); Dog dog = new Dog(name); return dog; } public static void main(String[] args) { String json = "{\"animal\":{\"name\":\"I am a dog\"}}"; Gson gson = new GsonBuilder().registerTypeAdapter(Dog.class, new DogDeserialiser()).create(); Type animalType = new TypeToken<Animal<Dog>>() { }.getType(); Animal<Dog> animal = gson.fromJson(json, animalType); System.out.println(animal.get().getName()); } }i):GSON擴展策略
在缺省的狀況下,GSON試着將java對象中的全部屬性映射到json中相一致的屬性中。可是在一些特殊的狀況下咱們嘗試去控制這個操做。這個是有一些方法實現的。
1.經過自定義註解的方式而且忽略被註解的域。
2.經過集成ExclusionStrategy 接口的方式自定義來實現,須要實現的方法有public boolean shouldSkipField(FieldAttributes f); and public boolean shouldSkipClass(Class clazz);
3.經過使用@Expose 註解,而後在GsonBuilder上面使用excludeFieldsWithoutExposeAnnotation(),這個方法,除非使用 @Expose 這個註解,否 則咱們忽略全部的域。
舉例:ExclusionExample.java
import java.awt.Color; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class ExclusionExample { public static void main(String[] args) { Cat cat = new Cat(); cat.setName("Cat"); cat.setAge(1); cat.setColor(Color.BLACK); cat.setCountry("US"); Gson gson = new GsonBuilder().serializeNulls().setExclusionStrategies(new CustomExclusionStrategy(Color.class)) .excludeFieldsWithoutExposeAnnotation().create(); System.out.println(gson.toJson(cat)); // 打印結果 {"name":"Cat","lazy":null} } }
Cat.java
import java.awt.Color; import com.google.gson.annotations.Expose; public class Cat { @Expose private String name; private int age; private Color color; @Expose @Country private String country; @Expose private Boolean lazy = null; public void setAge(int age) { this.age = age; } public void setName(String name) { this.name = name; } public void setColor(Color color) { this.color = color; } public int getAge() { return age; } public String getName() { return name; } public Color getColor() { return color; } public void setCountry(String country) { this.country = country; } public String getCountry() { return country; } public void setLazy(Boolean lazy) { this.lazy = lazy; } public Boolean getLazy() { return lazy; } }
CustomExclusionStrategy.java
import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; public class CustomExclusionStrategy implements ExclusionStrategy { private Class classToExclude; public CustomExclusionStrategy(Class classToExclude) { this.classToExclude = classToExclude; } @Override public boolean shouldSkipField(FieldAttributes f) { if (f.getAnnotation(Country.class) == null) return false; return true; } @Override public boolean shouldSkipClass(Class<?> clazz) { if (clazz.equals(classToExclude)) return true; return false; } }
4.結束
Gson功能的強大可見一斑,並且非常簡介,畢竟是大牌廠商的產品,果真是不同,固然還有不少功能有待挖掘,最好的是閱讀源碼,這樣能夠收穫更大。