Java中Gson的使⽤详解
JSON 是⼀种⽂本形式的数据交换格式,它⽐XML更轻量、⽐⼆进制容易阅读和编写,调式也更加⽅便;解析和⽣成的⽅式很多,Java中最常⽤的类库有:JSON-Java、Gson、Jackson、FastJson等
⼀、Gson的基本⽤法
Gson提供了fromJson() 和toJson() 两个直接⽤于解析和⽣成的⽅法,前者实现反序列化,后者实现了序列化;同时每个⽅法都提供了重载⽅法
(1)基本数据类型的解析
Gson gson = new Gson();
int i = gson.fromJson("100", int.class); //100
double d = gson.fromJson("\"99.99\"", double.class); //99.99
boolean b = gson.fromJson("true", boolean.class);  // true
String str = gson.fromJson("String", String.class);  // String
(2)基本数据类型的⽣成 
Gson gson = new Gson();
String jsonNumber = Json(100);    // 100
String jsonBoolean = Json(false);  // false
String jsonString = Json("String"); //"String"
(3)POJO类的⽣成与解析
public class User {
//省略其它
public String name;
public int age;
public String emailAddress;
}
⽣成JSON: 
Gson gson = new Gson();
User user = new User("张三",24);
String jsonObject = Json(user); // {"name":"张三kidou","age":24}
解析JSON: 
Gson gson = new Gson();
String jsonString = "{\"name\":\"张三\",\"age\":24}";
User user = gson.fromJson(jsonString, User.class);
⼆、属性重命名 @SerializedName 注解的使⽤
从上⾯POJO的⽣成与解析可以看出json的字段和值是的名称和类型是⼀⼀对应的,但也有⼀定容错机制(如第⼀个例⼦第3⾏将字符串的99.99转成double 型),但有时候也会出现⼀些不和谐的情况,如:
期望的json格式:{"name":"张三","age":24,"emailAddress":"zhangsan@ceshi"}
实际:{"name":"张三","age":24,"email_address":"zhangsan@ceshi"}java switch case string
Gson在序列化和反序列化时需要使⽤反射,⼀般各类库都将注解放到annotations包下,打开源码在le.gson包下有⼀个annotations,⾥⾯有⼀个SerializedName的注解类。对于json中email_address这个属性对应POJO的属性则变成: 
@SerializedName("email_address")
public String emailAddress;
为POJO字段提供备选属性名:SerializedName注解提供了两个属性,上⾯⽤到了其中⼀个,别外还有⼀个属性alternate,接收⼀个String数组
注:alternate需要2.4版本
@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
public String emailAddress;
/
/当三个属性(email_address、email、emailAddress)都中出现任意⼀个时均可以得到正确的结果
//当多种情况同时出时,以最后⼀个出现的值为准。
Gson gson = new Gson();
String json = "{\"name\":\"张三kidou\",\"age\":24,\"emailAddress\":\"zhangsan@ceshi\",\"email\":\"zhangsan_2@ceshi\",\"email_address\":\"zhangsan_3@ceshi\"}";
User user = gson.fromJson(json, User.class);
System.out.ailAddress); // zhangsan_3@example
三、Gson中使⽤泛型
例如:JSON字符串数组:["Android","Java","PHP"]
当要通过Gson解析这个json时,⼀般有两种⽅式:使⽤数组,使⽤List;⽽List对于增删都是⽐较⽅便的,所以实际使⽤是还是List⽐较多
数组⽐较简单:
Gson gson = new Gson();
String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);
对于List将上⾯的代码中的 String[].class 直接改为 List<String>.class 是不⾏的,对于Java来说List<String> 和List<User> 这俩个的字节码⽂件只⼀个那就是List.class,这是Java泛型使⽤时要注意的问题泛型擦除
为了解决的上⾯的问题,Gson提供了TypeToken来实现对泛型的⽀持,所以将以上的数据解析为List<String>时需要这样写
Gson gson = new Gson();
String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
/
/TypeToken的构造⽅法是protected修饰的,所以上⾯才会写成new TypeToken<List<String>>() {}.getType() ⽽不是 new TypeToken<List<String>>().getType()
泛型解析对接⼝POJO的设计影响
泛型的引⼊可以减少⽆关的代码: 
{"code":"0","message":"success","data":{}}
{"code":"0","message":"success","data":[]}
我们真正需要的data所包含的数据,⽽code只使⽤⼀次,message则⼏乎不⽤,如果Gson不⽀持泛型或不知道Gson⽀持泛型的同学⼀定会这么定义POJO
public class UserResponse {
public int code;
public String message;
public User data;
}
当其它接⼝的时候⼜重新定义⼀个XXResponse将data的类型改成XX,很明显code,和message被重复定义了多次,通过泛型可以将code和message字段抽取到⼀个Result的类中,这样只需要编写data字段所对应的POJO即可:
public class Result<T> {
public int code;
public String message;
public T data;
}
//对于data字段是User时则可以写为 Result<User> ,当是个列表的时候为 Result<List<User>>
四、Gson的流式反序列化
(1)⾃动⽅式
Gson提供了fromJson()和toJson() 两个直接⽤于解析和⽣成的⽅法,前者实现反序列化,后者实现了序列化。同时每个⽅法都提供了重载⽅法 
Gson.fromJson(Reader,Class);
Gson.fromJson(String,Class);
Gson.fromJson(Reader,Type);
Gson.fromJson(String,Type);
(2)⼿动⽅式:⼿动的⽅式就是使⽤stream包下的JsonReader类来⼿动实现反序列化,和Android中使⽤pull解析XML是⽐较类似的
String json = "{\"name\":\"张三\",\"age\":\"24\"}";
User user = new User();
JsonReader reader = new JsonReader(new StringReader(json));
reader.beginObject();
while (reader.hasNext()) {
String s = Name();
switch (s) {
case "name":
user.name = String();
break;
case "age":
user.age = Int(); //⾃动转换
break;
case "email":
break;
}
}
System.out.println(user.name); //张三
System.out.println(user.age);  // 24
System.out.ail); //zhangsan@ceshi
⾃动⽅式最终都是通过JsonReader来实现的,如果第⼀个参数是String类型,那么Gson会创建⼀个StringReader转换成流操作
五、Gson的流式序列化
(1)⾃动⽅式
//PrintStream(System.out) 、StringBuilder、StringBuffer和*Writer都实现了Appendable接⼝。 
Gson gson = new Gson();
User user = new User("张三",24,"zhangsan@ceshi");
(2)⼿动⽅式
JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));
writer.beginObject() // throws IOException
.name("name").value("张三")
.name("age").value(24)
.name("email").nullValue() //演⽰null
.endObject(); // throws IOException
writer.flush(); // throws IOException
//{"name":"张三","age":24,"email":null}
//除了beginObject、endObject还有beginArray和endArray,两者可以相互嵌套,注意配对即可。beginArray后不可以调⽤name⽅法,同样beginObject后在调⽤value之前必须要调⽤name⽅法。
六、使⽤GsonBuilder导出null值、格式化输出、⽇期时间
⼀般情况下Gson类提供的 API已经能满⾜⼤部分的使⽤场景,但有时需要更多特殊、强⼤的功能时,这时候就引⼊⼀个新的类 GsonBuilder。GsonBuilder从名上也能知道是⽤于构建Gson实例的⼀个类,要想改变Gson默认的设置必须使⽤该类配置Gson
GsonBuilder⽤法: 
//各种配置 //⽣成配置好的Gson
Gson gson = new GsonBuilder().create();
(1)Gson在默认情况下是不动导出值null的键的,如:
public class User {
public String name;
public int age;
   //省略
public String email;
}
Gson gson = new Gson();
User user = new User(张三",24);
System.out.Json(user)); //{"name":"张三","age":24}
//email字段是没有在json中出现的,当在调试时需要导出完整的json串时或API接中要求没有值必须⽤Null时,就会⽐较有⽤。
使⽤⽅法:
Gson gson = new GsonBuilder().serializeNulls() .create();
User user = new User("张三", 24);
System.out.Json(user)); //{"name":"张三","age":24,"email":null}
格式化输出、⽇期时间及其它:
Gson gson = new GsonBuilder()
//序列化null
.serializeNulls()
// 设置⽇期时间格式,另有2个重载⽅法
// 在序列化和反序化时均⽣效
.setDateFormat("yyyy-MM-dd")
// 禁此序列化内部类
.disableInnerClassSerialization()
//⽣成不可执⾏的Json(多了 )]}' 这4个字符)
.generateNonExecutableJson()
//禁⽌转义html标签
.disableHtmlEscaping()
/
/格式化输出
.setPrettyPrinting()
.create();
//:内部类(Inner Class)和嵌套类(Nested Class)的区别
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。