十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶(hù) + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專(zhuān)業(yè)推廣+無(wú)憂(yōu)售后,網(wǎng)站問(wèn)題一站解決
這篇文章主要講述了Gson的使用.包括從最基礎(chǔ)的基本類(lèi)型的序列化,到對(duì)象,數(shù)組,集合,再到Gson注解,Gson Builder,再到格式化,自定義序列化與反序列化等內(nèi)容.
另外文章篇幅較長(zhǎng),建議挑選所需部分查看.所有例子都提供了完整源碼,在文章的后面.
創(chuàng)新互聯(lián)公司專(zhuān)注于青原企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,商城網(wǎng)站制作。青原網(wǎng)站建設(shè)公司,為青原等地區(qū)提供建站服務(wù)。全流程按需定制網(wǎng)站,專(zhuān)業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)公司專(zhuān)業(yè)和態(tài)度為您提供的服務(wù)
JSON全稱(chēng)為JavaScript Object Notation,一種輕量級(jí)的數(shù)據(jù)交換格式.
類(lèi)似于XML但比XML更小,更易解析.
Gson是Google提供的可以使Java對(duì)象與JSON互轉(zhuǎn)的類(lèi)庫(kù),可將Java對(duì)象轉(zhuǎn)換為JSON,也可將JSON轉(zhuǎn)換成Java對(duì)象.
目前最新的是2.8.6版本.
dependencies {
implementation 'com.google.code.gson:gson:2.8.6'
}
com.google.code.gson
gson
2.8.6
點(diǎn)擊下載.
int intJSON = 1;
long longJSON = 1L;
double doubleJSON = 1.0;
float floatJSON = 1.0f;
byte byteJSON = 1;
char charJSON = 'G';
short shortJSON = 1;
boolean boooleanJSON = true;
System.out.println(gson.toJson(intJSON));
System.out.println(gson.toJson(longJSON));
System.out.println(gson.toJson(doubleJSON));
System.out.println(gson.toJson(floatJSON));
System.out.println(gson.toJson(byteJSON));
System.out.println(gson.toJson(charJSON));
System.out.println(gson.toJson(shortJSON));
System.out.println(gson.toJson(boooleanJSON));
System.out.println("----------------------------------------");
System.out.println(gson.fromJson("1",Integer.class));
System.out.println(gson.fromJson("1.0",Double.class));
System.out.println(gson.fromJson("1",Long.class));
System.out.println(gson.fromJson("true",Boolean.class));
System.out.println(gson.fromJson("B",Character.class));
cdn.xitu.io/2019/12/9/16ee6c9f1e5fa1c5?w=455&h=304&f=png&s=5737">
就是對(duì)應(yīng)輸出,沒(méi)啥好說(shuō)的.
Gson gson = new Gson();
System.out.println(gson.toJson(new A()));
String str = "{'field':'gggg','field2':33,'field3':'G','field4':'true'}";
A a = gson.fromJson(str,A.class);
System.out.println(a.getField1());
System.out.println(a.getField2());
System.out.println(a.getField3());
System.out.println(a.getField4());
A類(lèi):
class A
{
private String field1 = "123";
private int field2 = 1;
private char field3 = 'X';
private Boolean field4 = true;
}
序列化出來(lái)的對(duì)象用{}表示.
反序列化時(shí),注意格式,注意名字對(duì)應(yīng),用單引號(hào)引起來(lái),還有char會(huì)自動(dòng)變?yōu)镾tring類(lèi)型,另外對(duì)于布爾類(lèi)型可以加單引號(hào)或不加單引號(hào),都可以正常反序列化.
int [] a = new int []{1,2,3};
double [] b = new double []{1.0,2.0,3.0};
String [] c = new String []{"123","456"};
System.out.println(gson.toJson(a));
System.out.println(gson.toJson(b));
System.out.println(gson.toJson(c));
int [] aa = gson.fromJson("[6,7,8]",int [].class);
double [] bb = gson.fromJson("[6.0,8.0,9.0]",double [].class);
String [] cc = gson.fromJson("['123123','5464']",String [].class);
System.out.println(Arrays.toString(aa));
System.out.println(Arrays.toString(bb));
System.out.println(Arrays.toString(cc));
對(duì)普通數(shù)組的話(huà),{}變成了[].
還有就是反序列化時(shí),默認(rèn)會(huì)在逗號(hào)后面添一個(gè)空格.
List list = new ArrayList<>();
list.add("123");
list.add("456");
System.out.println(gson.toJson(list));
List list2 = new ArrayList<>();
list2.add(new AAAA());
list2.add(new AAAA("45345",8888,false));
System.out.println(gson.toJson(list2));
System.out.println("---------------------------------");
Type type = new TypeToken>(){}.getType();
String strList = "['234234','45457']";
List list3 = gson.fromJson(strList, type);
System.out.println(list3);
String strList2 = "[" +
"{'field1':'9999','field2':666,'field3':'true'}" +
"," +
"{'field1':'sdlkfkl','field2':-234234,'field3':'false'}" +
"]";
List list4 = gson.fromJson(strList2, new TypeToken>(){}.getType());
System.out.println(list4);
class AAAA
{
private String field1 = "123";
private int field2 = 5;
private boolean field3 = true;
}
序列化沒(méi)什么問(wèn)題,直接toJson即可,反序列化時(shí),需要配合java.lang.reflect.Type使用,明確指出所要轉(zhuǎn)換的類(lèi)型:
Type type = new TypeToken>(){}.getType();
TypeToken
List序列化出來(lái)的用[]表示.
Map map = new HashMap<>();
map.put("123",88);
map.put("2349",999);
System.out.println(gson.toJson(map));
String str = "{'123':23423423,'9999':-234234}";
Map map2 = gson.fromJson(str, new TypeToken
Map同樣序列化時(shí)直接toJson,反序列化時(shí)使用java.lang.reflect.Type.Map序列化出來(lái)的用{}表示.
Set set = new HashSet<>();
set.add("123123");
set.add("2349594");
set.add("-234()@#$@#");
System.out.println(gson.toJson(set));
String str = "['38483','@*#$(@#$)','SDG']";
Set set2 = gson.fromJson(str, new TypeToken>(){}.getType());
set2.stream().forEach(System.out::println);
set序列化出來(lái)的用[]表示.
System.out.println(gson.toJson(new AAA()));
String str = "{'field2':333,'field3':null}";
System.out.println(gson.fromJson(str, AAA.class));
class AAA
{
private String field1 = null;
private Integer field2 = null;
private Double field3 = 3.0;
@Override
public String toString()
{
return "field1:"+field1+",field2:"+field2+",field3:"+field3;
}
}
Gson會(huì)忽略空值,在序列化時(shí)看不到null對(duì)應(yīng)的鍵值對(duì),反序列化時(shí),直接對(duì)應(yīng)為空.
一個(gè)對(duì)象里面包含了List,Map,Set,null.
System.out.println(gson.toJson(new Test()));
class Test
{
private List listField = new ArrayList<>();
private Map mapField = new HashMap<>();
private Set setField = new HashSet<>();
private List userListFiled = new ArrayList<>();
private Map userMapField = new HashMap<>();
private Set userSetField = new HashSet<>();
private Set nullSetField = null;
private Map nullMapField = null;
private List nullListField = null;
private Long longField = 23423423423L;
private int intField = 234234;
private Double doubleField = 234234.23423;
private User userField = new User();
{
listField.add("234234");
mapField.put("23432",-234.0);
setField.add(-23423);
userListFiled.add(new User("3459",-23423,new int []{4,5,5}));
userListFiled.add(new User());
userMapField.put("()",new User());
userMapField.put("------", new User("345345",3434,new int []{4,44}));
userSetField.add(new User());
userSetField.add(new User());
}
}
class User
{
private String name = "noName";
private int age = 0;
private int [] nums = new int[]{2,3,4};
public User()
{
}
public User(String name,int age,int [] nums)
{
this.name = name;
this.age = age;
this.nums = nums;
}
}
這個(gè)就不反序列化了,可以看到對(duì)象,Map用{},List,Set用[].與上面的一致.
SerializedName注解有兩個(gè)參數(shù),分別是value與alternate.SerializedName由注解名字可以知道與序列化成的Json名字有關(guān).
默認(rèn)情況下,json的鍵名與對(duì)象的字段名一致,@SerializedName可以解決序列化/反序列化時(shí)json鍵名與對(duì)象字段名不一致的問(wèn)題,使其將json可以正確映射到對(duì)應(yīng)的字段.
單獨(dú)使用一個(gè)參數(shù)時(shí),即@SerializedName("xxx")或@SerializedName(value="xxx"),序列化時(shí),對(duì)象字段會(huì)變?yōu)锧SerializedName中的值,反序列化時(shí),若不是@SerializedName()中的值則不會(huì)反序列化:
public class SerializedNameValueTest
{
public static void main(String[] args) {
Gson gson = new Gson();
System.out.println(gson.toJson(new SerializedNameValueTest().new User()));
String str = "{'this is a name':'what????','this is an age':13,'email':'33333@222.com'}";
System.out.println(gson.fromJson(str,User.class));
String str2 = "{'name':'askldfklaslk','age':-222,'email':'234234@23423.com'}";
System.out.println(gson.fromJson(str2, User.class));
}
class User
{
@SerializedName("this is a name")
private String name = "123";
@SerializedName("this is an age")
private int age = 0;
private String email = "xxx@xxx.com";
private double[] nums = new double[] { 1.0, 2.0 };
@Override
public String toString() {
return "name:" + name + ",age:" + age + ",eamil:" + email + ",nums:" + Arrays.toString(nums);
}
}
}
最后一個(gè)反序列化不成功,因?yàn)?name'不對(duì)應(yīng)@SerializedName()中的'this is a name'.
同時(shí)使用兩者可以解決上面的問(wèn)題,即name字段--->json中的'this is a name'--->name字段:
public class SerializedNameValueAndAlternateTest
{
public static void main(String[] args) {
Gson gson = new Gson();
System.out.println(gson.toJson(new SerializedNameValueAndAlternateTest().new User()));
String str = "{'this is a name':'what????','this is an age':13,'email':'33333@222.com'}";
System.out.println(gson.fromJson(str, User.class));
String str2 = "{'name':'askldfklaslk','age':-222,'email':'234234@23423.com'}";
System.out.println(gson.fromJson(str2, User.class));
}
class User {
@SerializedName(value = "this is a name",alternate = "name")
private String name = "123";
@SerializedName(value = "this is an age",alternate = "age")
private int age = 0;
private String email = "xxx@xxx.com";
private double[] nums = new double[] { 1.0, 2.0 };
@Override
public String toString() {
return "name:" + name + ",age:" + age + ",eamil:" + email + ",nums:" + Arrays.toString(nums);
}
}
}
alternate就是為反序列化準(zhǔn)備的,若找不到value中對(duì)應(yīng)的值,則尋找alternate對(duì)應(yīng)的值,找不到再設(shè)為null.
若同時(shí)存在value與alternate:
String str3 = "{'name':'altername','this is a name':'value'}";
System.out.println(gson.fromJson(str3, User.class));
String str4 = "{'this is a name':'value','name':'altername'}";
System.out.println(gson.fromJson(str4, User.class));
則以"最晚"出現(xiàn)的值為標(biāo)準(zhǔn).
@Expose可以忽略某個(gè)字段,有兩個(gè)參數(shù):
默認(rèn)情況下都是true,分別表示序列化與反序列化.
System.out.println(gson.toJson(new User()));
class User
{
@Expose(serialize = false)
private String name = "123";
@Expose(deserialize = false)
private int age = 0;
@Expose(serialize = false,deserialize = false)
private String email = "xxx@xxx.com";
@Expose(serialize = true,deserialize = true)
private double [] nums = new double [] {1.0,2.0};
}
name不允許序列化,age不允許反序列化,email不允許序列化與反序列化,nums既允許也允許反序列化.(此時(shí)效果等于沒(méi)加@Expose)
輸出:
咦?好像沒(méi)用的樣子?
因?yàn)镚son對(duì)象會(huì)默認(rèn)忽略@Expose,想要@Expose生效需要使用Gson Builder:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.excludeFieldsWithoutExposeAnnotation();
Gson gson = gsonBuilder.create();
System.out.println(gson.toJson(new User()));
String str = "{'name':'234','age':-3,'email':'23423','nums':[3,4,3]}";
System.out.println(gson.fromJson(str, User.class));
class User
{
@Expose(serialize = false)
private String name = "123";
@Expose(deserialize = false)
private int age = 0;
@Expose(serialize = false,deserialize = false)
private String email = "xxx@xxx.com";
@Expose(serialize = true,deserialize = true)
private double [] nums = new double [] {1.0,2.0};
@Override
public String toString()
{
return "name:"+name+",age:"+age+",eamil:"+email+",nums:"+Arrays.toString(nums);
}
}
不能反序列化age與email,輸出的是age與email的默認(rèn)值.
前面的例子基本上都是通過(guò)
Gson gson = new Gson();
來(lái)直接實(shí)例化一個(gè)Gson來(lái)使用Gson的,使用Gson Builder可以設(shè)置Gson的某些屬性,使用其中的create()返回一個(gè)Gson.
創(chuàng)建一個(gè)簡(jiǎn)單的Gson,通過(guò)create()創(chuàng)建:
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
使用
gsonBuilder.setFieldNamingPolicy();
設(shè)置json中鍵的命名規(guī)則.6個(gè)值可選:
public class NamingRulesTest
{
public static void main(String[] args) {
NamingRulesTest n = new NamingRulesTest();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY);
System.out.println(gsonBuilder.create().toJson(n.new User()));
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES);
System.out.println(gsonBuilder.create().toJson(n.new User()));
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DOTS);
System.out.println(gsonBuilder.create().toJson(n.new User()));
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
System.out.println(gsonBuilder.create().toJson(n.new User()));
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE);
System.out.println(gsonBuilder.create().toJson(n.new User()));
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES);
System.out.println(gsonBuilder.create().toJson(n.new User()));
}
class User
{
@SuppressWarnings("unused")
private String Name_Name_name = "123";
@SuppressWarnings("unused")
private int _age_age_Age_age = 645;
@SuppressWarnings("unused")
private double numsNumsNums = 34.45;
}
}
注意,若某個(gè)字段有了@SerializedName,則這個(gè)字段遵循@SerializedName的策略.
重寫(xiě)FieldNamingStrategy中的translateName(Field field),把自定義的FieldNamingStrategy傳遞給GsonBuilder的setFieldNamingStrategy().
比如想要前綴加上某人的名字:
public class CustomNamingRulesTest
{
public static void main(String[] args) {
FieldNamingStrategy myNamingStrategy = new FieldNamingStrategy(){
@Override
public String translateName(Field field) {
return "kr"+field.getName();
}
};
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingStrategy(myNamingStrategy);
Gson gson = gsonBuilder.create();
System.out.println(gson.toJson(new CustomNamingRulesTest().new User()));
}
class User
{
@SuppressWarnings("unused")
private String name = "123";
@SuppressWarnings("unused")
private int num = 5;
}
}
默認(rèn)情況下,Gson實(shí)例不允許序列化null,如果想要序列化null,借助GsonBuilder的serializeNulls()方法:
public class NullTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeNulls();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES);
System.out.println(gsonBuilder.create().toJson(new NullTest().new User()));
}
class User
{
@SuppressWarnings("unused")
private String thisIsANullField;
@SuppressWarnings("unused")
private Integer andThisIsANullFieldToo;
}
}
前面已經(jīng)接觸到了@Expose這樣的排除策略,下面看看更加強(qiáng)大的配合GsonBuilder使用的排除策略.主要有四種:屬性名排除,類(lèi)型排除,修飾符排除,@Expose排除.
public class ExclusionNameTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeNulls();
ExclusionStrategy exclusionName = new ExclusionStrategy(){
@Override
public boolean shouldSkipField(FieldAttributes f)
{
return f.getName().endsWith("e");
}
@Override
public boolean shouldSkipClass(Class> arg0) {
return false;
}
};
gsonBuilder.setExclusionStrategies(exclusionName);
System.out.println(gsonBuilder.create().toJson(new ExclusionNameTest().new User()));
}
class User
{
private String name;
private int num;
}
}
排除字段名以e結(jié)尾的字段.下面是重點(diǎn):
public boolean shouldSkipField(FieldAttributes f)
{
return f.getName().endsWith("e");
}
重寫(xiě)的shouldSkipField從名字可以看出跳過(guò)某些字段,返回true表示跳過(guò),即排除這個(gè)字段.上面的例子中若名字以e結(jié)尾則跳過(guò),因此輸出:
public class ExclusionTypeTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeNulls();
ExclusionStrategy exclusionType = new ExclusionStrategy(){
@Override
public boolean shouldSkipField(FieldAttributes arg0) {
return false;
}
@Override
public boolean shouldSkipClass(Class> cls) {
return cls == String.class;
}
};
gsonBuilder.setExclusionStrategies(exclusionType);
System.out.println(gsonBuilder.create().toJson(new ExclusionNameTest().new User()));
}
class User
{
@SuppressWarnings("unused")
private String name;
@SuppressWarnings("unused")
private int num;
}
}
重寫(xiě)的shouldSkipClass表示要跳過(guò)的類(lèi),這里跳過(guò)了String,只剩下num.
@Override
public boolean shouldSkipClass(Class> cls) {
return cls == String.class;
}
這個(gè)不用重寫(xiě)方法了,直接使用GsonBuilder的excludeFieldsWithModifiers(),參數(shù)是java.lang.reflect.Modifier:
這個(gè)可選的比較多就不一一列舉了,只選了一個(gè)final的例子:
public class ExclusionModifierTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.excludeFieldsWithModifiers(Modifier.FINAL);
System.out.println(gsonBuilder.create().toJson(new User()));
}
}
class User
{
@SuppressWarnings("unused")
private final String name = "123";
@SuppressWarnings("unused")
private static int num;
}
這個(gè)準(zhǔn)確來(lái)說(shuō)是排除沒(méi)有被@Expose注解的字段:
public class ExclusionExposeTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.excludeFieldsWithoutExposeAnnotation();
System.out.println(gsonBuilder.create().toJson(new ExclusionExposeTest().new User()));
}
class User
{
@SuppressWarnings("unused")
private String name;
@SuppressWarnings("unused")
private int num;
@Expose(serialize = true,deserialize = true)
private int age;
}
}
這是有關(guān)于反序列化時(shí)JSON的容錯(cuò)機(jī)制的問(wèn)題,因?yàn)橥ǔ?lái)說(shuō)將一個(gè)對(duì)象通過(guò)Gson轉(zhuǎn)換成json沒(méi)什么大問(wèn)題,但是將json轉(zhuǎn)換為對(duì)象的時(shí)候就...就難說(shuō)了,因?yàn)椴恢朗欠穹蠘?biāo)準(zhǔn)的json格式,因此Gson提供了一定的容錯(cuò)機(jī)制,就是Lenient.
Lenient翻譯過(guò)來(lái)是"寬容的"的意思,可以通過(guò):
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setLenient();
開(kāi)啟.
Gson內(nèi)部有一個(gè)JsonReader類(lèi),默認(rèn)情況下,JsonReader是嚴(yán)格的且僅接受符合RFC 4627標(biāo)準(zhǔn)的json(RFC 4627標(biāo)準(zhǔn)可以看看這里),設(shè)置為lenient后可以"容忍"以下幾種錯(cuò)誤:
設(shè)置setLenient()后,Gson會(huì)盡可能解析有錯(cuò)誤的json,若實(shí)在無(wú)能為力,會(huì)拋出MalformedJsonException異常.
下面是一個(gè)不嚴(yán)格的json的例子:
public class LenientTest
{
public static void main(String[] args)
{
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setLenient();
String str = "{'name'='234';'num'=6}";
System.out.println(gsonBuilder.create().fromJson(str,User.class));
}
class User
{
private String name;
private int num;
@Override
public String toString()
{
return "name:"+name+",num:"+num;
}
}
}
下面是一個(gè)異常的例子:
String errorStr = "{'name'=????,,,,,,}";
System.out.println(gsonBuilder.create().fromJson(errorStr,User.class));
先看一個(gè)例子:
public class FloatTest
{
public static void main(String[] args) {
Gson gson = new Gson();
System.out.println(gson.toJson(new FloatTest().new User()));
}
class User
{
@SuppressWarnings("unused")
private float f = Float.POSITIVE_INFINITY;
}
}
會(huì)報(bào)錯(cuò):
它說(shuō)Infinity在JSON標(biāo)準(zhǔn)是一個(gè)非法值.想要重寫(xiě)這個(gè)行為需要使用GsonBuilder.serializeSpecialFloatingPointValues().
因?yàn)镴SON規(guī)范不允許NaN,-Infinity,Infinity,因此會(huì)報(bào)錯(cuò).下面使用GsonBuilder:
public class FloatTest
{
public static void main(String[] args) {
// Gson gson = new Gson();
// System.out.println(gson.toJson(new FloatTest().new User()));
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeSpecialFloatingPointValues();
System.out.println(gsonBuilder.create().toJson(new FloatTest().new User()));
}
class User
{
@SuppressWarnings("unused")
private float f = Float.POSITIVE_INFINITY;
}
}
直接輸出Infinity:
double也類(lèi)似:
public class DoubleTest
{
public static void main(String[] args)
{
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeSpecialFloatingPointValues();
System.out.println(gsonBuilder.create().toJson(new DoubleTest().new User()));
}
class User
{
@SuppressWarnings("unused")
private double ni = Double.NEGATIVE_INFINITY;
@SuppressWarnings("unused")
private double pi = Double.POSITIVE_INFINITY;
@SuppressWarnings("unused")
private double nan = Double.NaN;
}
}
通過(guò)@Since與@Until添加版本控制,控制某個(gè)版本在序列化與反序列化時(shí)忽略或忽略某個(gè)字段.
@Since表示從某個(gè)版本開(kāi)始這個(gè)字段不忽略,@Until表示這個(gè)版本后將忽略該字段.
需要配合GsonBuilder的setVersion使用,設(shè)定版本號(hào).
public class VersionTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeNulls();
System.out.println(gsonBuilder.setVersion(0.9).create().toJson(new VersionTest().new User()));
System.out.println(gsonBuilder.setVersion(1.0).create().toJson(new VersionTest().new User()));
System.out.println(gsonBuilder.setVersion(1.4).create().toJson(new VersionTest().new User()));
System.out.println(gsonBuilder.setVersion(1.5).create().toJson(new VersionTest().new User()));
}
class User
{
@Since(1.0)
private String name;
@Until(1.4)
private int num;
}
}
@Since的范圍包含了左區(qū)間端點(diǎn),@Until的范圍不包含右區(qū)間端點(diǎn).
可以使用setDateForamt()來(lái)格式化日期輸出:
gsonBuilder.setDateFormat(int style);
gsonBuilder.setDateFormat(String pattern);
gsonBuilder.setDateFormat(int dateStyle,int timeStyle);
第一個(gè)函數(shù)的參數(shù)為DateFormat中的常量值,第二個(gè)函數(shù)的參數(shù)是類(lèi)似SimpleDateFormat中的String,第三個(gè)函數(shù)的參數(shù)與第一個(gè)類(lèi)似,分開(kāi)日期與時(shí)間設(shè)置.
再說(shuō)以下setPrettyPrinting()這個(gè)函數(shù),看名字就知道,美化打印的.會(huì)加上空格.
public class FormatTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setPrettyPrinting();
System.out.println(gsonBuilder.setDateFormat(DateFormat.SHORT, DateFormat.SHORT).create().toJson(new FormatTest().new User()));
System.out.println(gsonBuilder.setDateFormat(DateFormat.SHORT,DateFormat.LONG).create().toJson(new FormatTest().new User()));
System.out.println(gsonBuilder.setDateFormat(DateFormat.MEDIUM, DateFormat.MEDIUM).create().toJson(new FormatTest().new User()));
System.out.println(gsonBuilder.setDateFormat(DateFormat.LONG, DateFormat.MEDIUM).create().toJson(new FormatTest().new User()));
System.out.println(gsonBuilder.setDateFormat(DateFormat.FULL, DateFormat.FULL).create().toJson(new FormatTest().new User()));
System.out.println(gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(new FormatTest().new User()));
}
class User
{
@SuppressWarnings("unused")
private Date date = new Date();
}
}
枚舉其實(shí)也與普通的字段類(lèi)似,序列化與反序列化正常操作.
public class EnumTest
{
public static void main(String[] args) {
Gson gson = new Gson();
System.out.println(gson.toJson(new EnumTest().new User()));
String str = "{\"season\":\"SUMMER\",\"name\":\"8888\"}";
System.out.println(gson.fromJson(str,User.class));
}
enum Season
{
SPRING,
SUMMER,
AUTUMN,
WINTER
}
class User
{
private Season season = Season.SPRING;
private String name = "123";
@Override
public String toString()
{
return "season:"+season.toString()+",name:"+name;
}
}
}
主要配合@SerializedName()使用,例如對(duì)于月份,可以使用1,2,3來(lái)表示:
public class EnumTest
{
public static void main(String[] args) {
Gson gson = new Gson();
System.out.println(gson.toJson(new EnumTest().new User()));
String str = "{\"season\":\"SUMMER\",\"name\":\"8888\",\"month\":\"2\"}";
System.out.println(gson.fromJson(str,User.class));
}
enum Season
{
SPRING,
SUMMER,
AUTUMN,
WINTER
}
class User
{
private Season season = Season.SPRING;
private String name = "123";
private Month month = Month.January;
@Override
public String toString()
{
return "season:"+season.toString()+",name:"+name+",month:"+month.toString();
}
}
enum Month
{
@SerializedName("1")
January,
@SerializedName("2")
February,
@SerializedName("3")
March,
@SerializedName("4")
April,
@SerializedName("5")
May,
@SerializedName("6")
June,
@SerializedName("7")
July,
@SerializedName("8")
August,
@SerializedName("9")
September,
@SerializedName("10")
October,
@SerializedName("11")
November,
@SerializedName("12")
December
}
}
這里主要說(shuō)一下反序列化泛型.因?yàn)樾蛄谢盒?..直接toJson()就好了.
想想這樣的情景:有一個(gè)待解析的Json String,類(lèi)型為L(zhǎng)ist
public List fromJSON(String json,Class cls);
好了,怎么寫(xiě)呢,之前用的是TypeToken()實(shí)現(xiàn)反序列化:
List integerList = new ArrayList<>();
integerList.add(3);
integerList.add(-999);
gson.toJson(integerList, new TypeToken>() {}.getType());
答案就是使用ParameterizedType:重寫(xiě)里面的getActualTypeArguments(),getOwnerTpye()與getRawType():
public class GenericsTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setPrettyPrinting();
Gson gson = gsonBuilder.create();
List integerList = new ArrayList<>();
integerList.add(3);
integerList.add(-999);
gson.toJson(integerList, new TypeToken>() {}.getType());
List stringList = new ArrayList<>();
stringList.add("12321");
stringList.add("(@)#$@#");
String t1 = gson.toJson(integerList);
String t2 = gson.toJson(stringList);
new GenericsTest().fromJSON(t1, Integer.class).stream().forEach(System.out::println);
new GenericsTest().fromJSON(t2, String.class).stream().forEach(System.out::println);
}
public List fromJSON(String json,Class cls)
{
return new Gson().fromJson(json,new ParameterizedTypeImpl(cls));
}
class ParameterizedTypeImpl implements ParameterizedType
{
private Class cls;
public ParameterizedTypeImpl(Class cls)
{
this.cls = cls;
}
@Override
public Type[] getActualTypeArguments()
{
return new Type[]{cls};
}
@Override
public Type getRawType()
{
return List.class;
}
@Override
public Type getOwnerType()
{
return null;
}
}
}
@Override
public Type[] getActualTypeArguments()
{
return new Type[]{cls};
}
返回實(shí)際參數(shù)類(lèi)型數(shù)組,在這里是String.class與Integer.class.
@Override
public Type getRawType()
{
return List.class;
}
返回聲明這個(gè)類(lèi)型的類(lèi)或接口,在這里是List.class.
@Override
public Type getOwnerType()
{
return null;
}
返回其成員之一的類(lèi)型,就是說(shuō)如果完全限定類(lèi)名為A.B,則返回A,在這里沒(méi)有A,因此為null.
定義好實(shí)現(xiàn)ParameterizedTpye接口的類(lèi)后,把它傳遞給fromJson()作為第二參數(shù),構(gòu)造方法的參數(shù)為L(zhǎng)ist
自定義序列化一般用于自定義簡(jiǎn)化json.
比如有一個(gè)User類(lèi):
class User
{
private String name = "123";
private String email = "xxx@xxx.com";
private int [] nums = new int [] {1,2,3};
}
想要不序列化name,可以使用@Expose(serialize = false),但是想要部分序列化nums,比如只是需要第一個(gè)nums[0],上面的@Expose,@SerializedName等注解都用不上,這時(shí)需要使用JsonSerializer自定義序列化,重寫(xiě)其中的:
public JsonElement serialize(T t,Type type,JsonSerializationContext context)
可以返回一個(gè)JsonObject,這里的JsonObject可以自定義添加屬性(即鍵值對(duì)).
需要配合GsonBuilder使用,創(chuàng)建了自己的JsonSerializer
public class SerializeCustomTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
JsonSerializer serializer = new JsonSerializer() {
@Override
public JsonElement serialize(User u,Type type,JsonSerializationContext context)
{
JsonObject object = new JsonObject();
object.addProperty("name",u.getName());
object.addProperty("email",u.getEmail());
object.addProperty("nums",u.getNums()[0]);
return object;
}
};
gsonBuilder.registerTypeAdapter(User.class,serializer);
System.out.println(gsonBuilder.create().toJson(new SerializeCustomTest().new User()));
}
class User
{
private String name = "123";
private String email = "xxx@xxx.com";
private int [] nums = new int [] {1,2,3};
public int [] getNums()
{
return nums;
}
public String getName()
{
return name;
}
public String getEmail()
{
return email;
}
}
}
自定義反序列化主要就是針對(duì)有多余鍵值對(duì)的json,比如User只需要name字段,但是傳來(lái)的json包含了諸如age這樣的鍵,因此只需挑選所需的進(jìn)行反序列化.與序列化類(lèi)似,首先定義自己的JsonDeserializer
public T deserialize(JsonElement,Type,JsonDeserializationContext);
返回一個(gè)自定義的反序列化的對(duì)象.最后在GsonBuilder中registerTypeAdapter()即可.
public class DeserializedCustomTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
JsonDeserializer deserializer = new JsonDeserializer() {
@Override
public User deserialize(JsonElement json,Type type,JsonDeserializationContext context)
{
JsonObject object = json.getAsJsonObject();
User user = new DeserializedCustomTest().new User(object.get("name").getAsString());
return user;
}
};
gsonBuilder.registerTypeAdapter(User.class, deserializer);
String str = "{\"aaa\":\"bbbb\",\"name\":\"this is a name\",\"age\":\"444\"}";
System.out.println(gsonBuilder.create().fromJson(str,User.class));
}
class User
{
private String name;
private int age;
public User(String name)
{
this.name = name;
}
@Override
public String toString()
{
return "name:"+name+",age:"+age;
}
}
}
可以設(shè)置反序列化時(shí)的默認(rèn)值,通過(guò)構(gòu)造方法實(shí)現(xiàn).比如json中沒(méi)有所需要的字段的值,默認(rèn)情況下為null,如果想要不為null,可以設(shè)定默認(rèn)值,對(duì)于對(duì)象可以設(shè)定構(gòu)造方法.
通過(guò)實(shí)現(xiàn)InstanceCreator
public class InstanceCustomTest
{
public static void main(String[] args) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(
AA.class,
new InstanceCustomTest().new AAInstance(
new InstanceCustomTest().new BB("123","456")
)
);
String str = "{\"name\":\"123123\"}";
System.out.println(gsonBuilder.create().fromJson(str, AA.class));
}
class AAInstance implements InstanceCreator
{
private BB bb;
public AAInstance(BB bb)
{
this.bb = bb;
}
@Override
public AA createInstance(Type type)
{
return new AA(bb);
}
}
class AA
{
private String name = "AA";
private BB bb;
public AA(BB bb)
{
this.bb = bb;
}
@Override
public String toString()
{
return "name:"+name+",bb:"+bb.toString();
}
}
class BB
{
private String field1;
private String field2;
public BB(String field1,String field2)
{
this.field1 = field1;
this.field2 = field2;
}
@Override
public String toString()
{
return "field1:"+field1+",field2:"+field2;
}
}
}
json沒(méi)有為BB類(lèi)設(shè)定值,采用默認(rèn)值.
這個(gè)是自定義序列化/反序列化的注解,可以簡(jiǎn)化JsonSerializer與JsonDeserializer.另外不用配合GsonBuilder使用,直接使用new Gson().toJson()/fromJson()即可,比直接使用JsonSerializer與JsonDeserializer要簡(jiǎn)單.
首先使一個(gè)類(lèi)實(shí)現(xiàn)JsonSerializer
class Serializer implements JsonSerializer
class ContainUser
{
private String userId = "x";
@JsonAdapter(Serializer.class)
private User user = new User();
}
public class JsonAdapterSerializeTest
{
public static void main(String[] args)
{
Gson gson = new Gson();
System.out.println(gson.toJson(new JsonAdapterSerializeTest().new ContainUser()));
}
class Serializer implements JsonSerializer
{
@Override
public JsonElement serialize(User u,Type type,JsonSerializationContext context)
{
JsonObject object = new JsonObject();
object.addProperty("name",u.getName());
object.addProperty("email",u.getEmail());
object.addProperty("nums",u.getNums()[0]);
return object;
}
}
class ContainUser
{
private String userId = "x";
@JsonAdapter(Serializer.class)
private User user = new User();
}
class User
{
private String name = "123";
private String email = "xxx@xxx.com";
private int [] nums = new int [] {1,2,3};
public int [] getNums()
{
return nums;
}
public String getName()
{
return name;
}
public String getEmail()
{
return email;
}
}
}
反序列化也類(lèi)似.
public class JsonAdapterDeserializeTest
{
public static void main(String[] args) {
Gson gson = new Gson();
String str = "{\"aaaa\":\"bbbb\",\"name\":\"this is a name\",\"age\":\"444\"}";
System.out.println(gson.fromJson(str,User.class));
}
class Deserialize implements JsonDeserializer
{
@Override
public User deserialize(JsonElement json,Type type,JsonDeserializationContext context)
{
JsonObject object = json.getAsJsonObject();
User user = new JsonAdapterDeserializeTest().new User(object.get("name").getAsString());
return user;
}
}
@JsonAdapter(Deserialize.class)
class User
{
private String name = "123";
public User()
{
}
public User(String name)
{
this.name = name;
}
@Override
public String toString()
{
return "name:"+name;
}
}
}
實(shí)現(xiàn)JsonDeserializer
注意@JsonAdapter注解只能添加在類(lèi)上.
所有例子的完整源碼.
github.
碼云.
Gson官方github.
1.Gson Tutorial Series by Future Studio
2.gson完全教程
3.gson教程
4.gson用戶(hù)指南
5.Gson User guide
6.gson