Gson的簡單用法
Gson介紹:
GSON是Google提供的用來在Java物件和JSON資料之間進行對映的Java類庫。可以將一個Json字元轉成一個Java物件,或者將一個Java轉化為Json字串。
特點: a、快速、高效
b、程式碼量少、簡潔
c、面向物件
d、資料傳遞和解析方便
Gson的pom依賴:
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.0</version> </dependency>
Gson的建立方式:
方式一:
Gson gson = new gson();
方式二:通過GsonBuilder(),可以配置多種配置。
Gson gson = new GsonBuilder() .setLenient()// json寬鬆 .enableComplexMapKeySerialization()//支援Map的key為複雜物件的形式 .serializeNulls() //智慧null .setPrettyPrinting()// 調教格式 .disableHtmlEscaping() //預設是GSON把HTML 轉義的 .create();
Gson的基本用法:
注:JavaBean:
@NoArgsConstructor @AllArgsConstructor @Setter @Getter @ToString @Builder public class PersonJson { private String name; private Integer age; private String hobby; } //hobby是在後面的例子中新增的。要麼就name,age兩個屬性,要麼就三個。 //上面的註解是lombok的註解,起到簡化Bean類的作用。
Gson提供了public String toJson(Objcet obj)方法,可以將物件轉化為json字串。
JavaBean轉化為json字串
public class IndexTest { PersonJson person; @Before public void prepare() { person = new PersonJson("慄霖",18); } @Test public void index() { Gson gson = new Gson(); System.out.println(gson.toJson(person)); System.out.println("---------------"); Gson gson1 = new GsonBuilder().create(); System.out.println(gson1.toJson(person)); } }
結果:
List Map 轉化為json字串
public class IndexTest { PersonJson person; List<PersonJson> list = new ArrayList<>(); Map<String,PersonJson> map = new HashMap<>(); @Before public void prepare() { person = new PersonJson("慄霖",18); list.add(person); map.put(person.getName(),person); } @Test public void index() { Gson gson = new Gson(); System.out.println("---->List convert json" + gson.toJson(list)); System.out.println("------------------------"); System.out.println("---->map convert json" + gson.toJson(map)); } }
結果:
Gson提供了public T fromJson(String jsonStr,T.class)方法,可以將json字串轉化為Java物件
json字串轉化為JavaBean
public class SecondTest { @Test public void index() { String jsonStr = "{\"name\":\"慄霖\",\"age\":\"18\"}"; Gson gson = new GsonBuilder().create(); PersonJson p = gson.fromJson(jsonStr,PersonJson.class); System.out.println("---->jsonStr convert javaBean " + p.getName() + " " + p.getAge()); } }
結果:
json字串轉化為list集合
public class SecondTest { @Test public void index() { String listJsonStr = "[{\"name\":\"慄霖\",\"age\":\"18\"},{\"name\":\"慄霖之雨\",\"age\":\"18\"}]"; Gson gson = new GsonBuilder().create(); List<PersonJson> list = gson.fromJson(listJsonStr,new TypeToken<ArrayList<PersonJson>>(){}.getType()); System.out.println("---->listJsonStr convert List " + list); } }
結果:
json的抽象基類JsonElemetn:
JsonNull其實就是Null欄位
public class SecondTest { @Test public void index() { //JsonNull jsonNull = new JsonNull();該方法已經過時 JsonNull jsonNull = JsonNull.INSTANCE; System.out.println("---->jsonNull " + jsonNull); } }
結果:
jsonPrimitive可以幫助我們獲取帶轉義字元的字串。這個就不寫了。感覺沒啥用到。
建立JsonObject:
可以通過addProperty(String,Object)向JsonObject新增屬性,跟hashmap類似。
public class SecondTest { @Test public void index() { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("name","慄霖"); jsonObject.addProperty("age",18); System.out.println("---->create jsonObject " + jsonObject); } }
結果:
建立JsonArray
public class SecondTest { @Test public void index() { JsonArray jsonArray = new JsonArray(); jsonArray.add("a"); jsonArray.add("b"); jsonArray.add("c"); jsonArray.add("d"); System.out.println("---->create jsonArray: " + jsonArray); } }
結果:
JsonObject巢狀陣列或者說JsonObject巢狀JsonArray
public class SecondTest { @Test public void index() { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("name","慄霖"); jsonObject.addProperty("age",18); JsonArray jsonArray = new JsonArray(); jsonArray.add("是碼農"); jsonArray.add("以前喜歡玩遊戲"); jsonArray.add("現在只敢小心積累"); jsonArray.add("只怕突然白了頭"); jsonObject.add("status",jsonArray); System.out.println("---->create jsonArray: " + jsonObject); } }
結果:
Gson註解
重新命名註解:@SerializedName
當你呼叫其他服務時,他們返回的json KEY值與你的Bean屬性名稱不對應怎麼辦?
這時候就需要@SerializedName啦。他可以幫助你解決這個問題!
實體類:
@NoArgsConstructor @AllArgsConstructor @Setter @Getter @ToString @Builder public class PersonJson { private String name; private Integer age; //這裡只是隨便舉個例子,千萬不要用中文!!! @SerializedName(value = "愛好") private String hobby; }
示例:
public class SecondTest { JsonObject jsonObject; JsonArray jsonArray; @Before public void index() { jsonObject = new JsonObject(); jsonObject.addProperty("name","慄霖"); jsonObject.addProperty("age",18); jsonArray = new JsonArray(); jsonArray.add("是碼農"); jsonArray.add("以前喜歡玩遊戲"); jsonArray.add("現在只敢小心積累"); jsonArray.add("只怕突然白了頭"); jsonObject.addProperty("愛好",jsonArray.toString()); } @Test public void formal() { Gson gson = new GsonBuilder().create(); PersonJson personJson = gson.fromJson(jsonObject.toString(),PersonJson.class); System.out.println("---->String: " + personJson); } }
結果:
@serializedName
除了value屬性外,還可以使用alternate屬性,這個值可以替換前面的值,將傳入的json進行修改。
注:value的值不能出現在alternate中,alternate是備選欄位。
@SerializedName(value = "hobby", alternate = {"interest","be fond of"})
過濾註解@Expose
注:預設是既可以序列化,也可以反序列化。一定要配合GsonBuilder一起使用
該註解是加在JavaBean的屬性上使用的。
配合這個使用哦Gson gson = new GsonBuilder().excludeFieldWithoutExposeAnnotation().create();
有四種使用方式:
1)不使用@Expose註解等同於@Expose(deserialize = false, serialize = false)不做任何解析
2)@Expose(deserialize = true, serialize = false)只解析使用,可以反序列化,不可以序列化。
3)@Expose(deserialize = false, serialize = true)可以序列化,不可以反序列化。
4)@Expose(deserialize = false, serialize = true)既可以序列化,也可以反序列化。
注:這裡的序列化指:將物件轉化為json字串。反序列化指:將json字串轉化成物件。
版本控制註解@Since(float v)
結合GsonBuilder().serVersion(n)使用。當n>=v時,才會解析。
注:也是加在JavaBean屬性上使用的。
版本控制註解@Util(float v)
與@Since相反,這次是n<v時才能夠解析。
使用TypeAdapter來實現序列化與反序列化。
使用TypeAdapter來序列化和反序列化
程式碼:
public class FiveTest { @Test public void index() { Gson gson = new GsonBuilder().create(); TypeAdapter<PersonJson> typeAdapter = gson.getAdapter(PersonJson.class); String json = "{\"name\":\"慄霖\",\"age\":\"18\",\"hobby\":\"我很是很喜歡FromSoftWare的。大愛宮崎英高,讚美太陽\"}"; PersonJson p = new PersonJson("慄霖",18,"混系列忠實粉絲"); System.out.println("---->序列化:是將物件轉化為字串 : " + typeAdapter.toJson(p)); try { System.out.println("---->反序列化:是將字串轉化為物件 : "+ typeAdapter.fromJson(json)); }catch (Exception e) { e.printStackTrace(); } } }
結果:
Gson的容錯機制
為什麼容錯:
如果Bean中定義的是int,但是返回的json對應的是一個""空字串怎麼辦?這就依賴到了Gson的容錯機制。
1)建立寬鬆Gson
遇到問題,停止解析,以防止報錯,功能相對較弱。
Gson gson = new GsonBuilder() .setLenient()//寬鬆 .create();
2)自定義TypeAdapter
該方法更傾向於整體防止出現異常。
public class ThirdTest { public static class PersonTypeAdapter extends TypeAdapter<PersonJson> { @Override public void write(JsonWriter jsonWriter, PersonJson personJson) throws IOException { jsonWriter.beginObject(); jsonWriter.name("name").value(personJson.getName()); jsonWriter.name("age").value(personJson.getAge()); jsonWriter.name("hobby").value(personJson.getHobby()); jsonWriter.endObject(); } @Override public PersonJson read(JsonReader jsonReader) throws IOException { PersonJson personJson = new PersonJson(); jsonReader.beginObject(); while (jsonReader.hasNext()) { switch (jsonReader.nextName()) { case "name": personJson.setName(jsonReader.nextString()); break; case "age": try { personJson.setAge(Integer.valueOf(jsonReader.nextString())); } catch (Exception e) { } break; case "hobby": personJson.setHobby(jsonReader.nextString()); } } jsonReader.endObject(); return personJson; } } @Test public void index() { Gson gson = new Gson(); String json = "{\"name\":\"慄霖\",\"age\":\"\",\"hobby\":\"籃球吧,讀書吧,steam吧\"}"; System.out.println("----> " + json ); try { PersonJson p1 = gson.fromJson(json,PersonJson.class); System.out.println("---->預設解析 " + p1); }catch (Exception e) { System.out.println("---->異常解析,這裡json字串缺失了age的值,真的是怕一轉眼就白了頭啊" +e); } Gson gson1 = new GsonBuilder().registerTypeAdapter(PersonJson.class,new PersonTypeAdapter()).create(); try { PersonJson p2 = gson1.fromJson(json,PersonJson.class); System.out.println("---->自定義Adapter 預設解析 "+p2); }catch (Exception e) { System.out.println("---->自定義adapter 異常解析" + e); } try { PersonTypeAdapter personTypeAdapter = new PersonTypeAdapter(); PersonJson p3 = personTypeAdapter.fromJson(json); System.out.println("---->自定義Adapter 預設解析 " + p3); }catch (Exception e){ System.out.println("---->自定義Adapter 異常解析 " +e); } } }
結果:
3)使用註解jsonAdapter,其實質也是自定義Adapter
該方法更傾向於某一個屬性的保護。
實體類:
public class PersonJson { private String name; @JsonAdapter(IntegerTypeAdapter.class) private Integer age; private String hobby; }
Adapter:
public class IntegerTypeAdapter extends TypeAdapter<Integer>{ @Override public void write(JsonWriter jsonWriter, Integer integer) throws IOException { jsonWriter.value(integer); } @Override public Integer read(JsonReader jsonReader) throws IOException { int i = 0; try { i = Integer.valueOf(jsonReader.nextString()); }catch (Exception e){} return i; } }
測試類:
public class FourTest { @Test public void index() { Gson gson = new Gson(); String json = "{\"name\":\"慄霖\",\"age\":\"\",\"hobby\":\"籃球吧,讀書吧,steam吧\"}"; try { PersonJson p1 = gson.fromJson(json,PersonJson.class); System.out.println("---->預設解析 " + p1); }catch (Exception e) { System.out.println("---->異常解析,這裡json字串缺失了age的值,真的是怕一轉眼就白了頭啊" +e); } try { PersonJson p2 = gson.fromJson(json,PersonJson.class); System.out.println("---->預設解析 " + p2); }catch (Exception e) { System.out.println("---->異常解析" + e); } } }