關于json谷羞,gson是最常用到的一個庫。
平常使用時我通常使用Gson gson = new Gson();的方式創(chuàng)建插勤。
但是最近在使用木哥給的一個volley工具時,出現(xiàn)了解析不出來的情況啦租,很是郁悶。
自己看了半天也沒找到原因荒揣。所以專門再吧gson的使用方法總結(jié)一下篷角。
Gson的api地址
Gson User Guide
google也有github page,哈哈,竟然有35頁的開源項目乳附。
new Gson()
我之前都是用的這種方式内地。。赋除。
Gson有兩個重要的方法阱缓,一個是toJson,一個是fromJson举农,也就是序列化和反序列化荆针。
比如解析下面這個gson串:
{
"name" : "Ravi Tamada",
"email" : "ravi8x@gmail.com",
"phone" : {
"home" : "08947 000000",
"mobile" : "9999999999"
}
}
先寫一個User
public class User {
private String name;
private String email;
private Phone phone;}
再寫一個Phone
public class Phone {
private String home;
private String mobile;}
接下來一切都簡單了
Gson gson = new Gson();
User user = gson.fromJson(response.toString(), User.class);
mTextViewVolley.setText(user.getName()+"\n"+user.getEmail()+"\n"+"phone:"+user.getPhone().getHome());
gson常用的方法示例
Gson gson = new Gson();
//序列化
MyObject myobj = new MyObject();
String jsonstr = gson .toJson(myobj);
//反序列化
MyObject myobj = gson.fromJson(jsonstr, MyObject.class);
//序列化數(shù)組
String[] days = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
String numbersJson = gson.toJson(days);
//序列化集合
List<String> myobjs = new ArrayList<String>();
String jsonstr = gson.toJson(myobjs);
//反序列化集合數(shù)組
List<MyObject> myobjs = gson.fromJson(str, new TypeToken<ArrayList<MyObject>>(){}.getType());
// Deserialization
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
PS:如果需要轉(zhuǎn)換的類包括泛型,那么也需要用到TypeToken颁糟,通過這個類可以獲取具體的類型
注解
然而Gson并沒有那么簡單航背。他還可以使用注解:
Expose
此注解作用在屬性上,表明當序列化和反序列化的時候棱貌,這個屬性將會暴露給Gson對象玖媚。這個注解只有當創(chuàng)建Gson對象時使用GsonBuilder方式創(chuàng)建并調(diào)用了GsonBuilder.excludeFieldsWithoutExposeAnnotation() 方法的時候才有效,否則無效婚脱。下面是一個介紹@Expose注解如何使用的例子:
publicclass User {
@Expose private String firstName;
@Expose(serialize = false) private String lastName;
@Expose (serialize = false, deserialize = false) private String emailAddress;
private String password;
}
如果你以new Gson()的方式創(chuàng)建Gson對象今魔,toJson()方法和fromJson() 方法在序列化和反序列化的時候?qū)僮鬟@4個屬性。然而障贸,如果你使用 Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()來創(chuàng)建Gson對象错森,Gson 的 toJson() 和 fromJson() 方法將會排除掉 password 字段,這是因為 password 字段沒有被注解 @Expose 所標記。 這個 Gson 對象同樣會排除 lastName 和 emailAddress 字段,因為注解@Expose的屬性 serialize 被設置成了 false患膛。類似的,Gson 將會在反序列化時排除掉 emailAddress 字段瓦阐,因為 deserialize被設置成了 false。
PS:
如果不希望有某些屬性锋叨,也可以使用transient屏蔽垄分,如:
transient int val;
SerializedName
用于修改屬性序列化成json之后的名字。
此注解作用在屬性上娃磺,表明這個屬性在序列化成Json的時候薄湿,需要將名字序列化成注解的value屬性指定的值。
這個注解將會覆蓋任何的FieldNamingPolicy, 包括默認的命名策略豺瘤。下面是一個介紹@SerializedName注解如何使用的例子:
publicclass SomeClassWithFields {
@SerializedName("name") privatefinal String someField;
private final String someOtherField;
public SomeClassWithFields(String a, String b) {
this.someField = a;
this.someOtherField = b;
}
}
序列化結(jié)果是:{"name":"a","someOtherField":"b"}
Since
使用@Since注解去維護版本吆倦,比如你有一個REST的API,并且有多個版本的JSON,如果下一個版本JSON中增加了字段坐求,但又不希望所有的版本都在使用這些字段的話蚕泽,就可以使用
publicclass Example33 {
publicstaticvoid main(String[] args) {
Gson gson = new GsonBuilder().setVersion(2.0).create();
String json = gson.toJson(new ExampleClass());
System.out.println("Output for version 2.0...");
System.out.println(json);
gson= new GsonBuilder().setVersion(1.0).create();
json = gson.toJson(new ExampleClass());
System.out.println("\nOutput for version 1.0...");
System.out.println(json);
gson= new Gson();
json = gson.toJson(new ExampleClass());
System.out.println("\nOutput for No version set...");
System.out.println(json);
}
}
class ExampleClass{
String field= "field";
// this is in version 1.0
@Since(1.0) String newField1 = "field 1";
// following will be included in the version 1.1
@Since(2.0) String newField2 = "field 2";
}
輸出為:
Output for version 2.0...
{"field":"field","newField1":"field 1","newField2":"field 2"}
Output for version 1.0...
{"field":"field","newField1":"field 1"}
Output for No version set...
{"field":"field","newField1":"field 1","newField2":"field 2"}
Until
和Since相反,如果下一個版本JSON中刪除了某個字段桥嗤,就可以使用须妻,原理同上。
GsonBulider
使用注釋之后泛领,我們創(chuàng)建gson就需要用到GsonBuilder
具體設置參數(shù)如下
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation() //不導出實體中沒有用@Expose注解的屬性
.enableComplexMapKeySerialization() //支持Map的key為復雜對象的形式
.setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")//時間轉(zhuǎn)化為特定格式
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)//會把字段首字母大寫,注:對于實體上使用了@SerializedName注解的不會生效.
.setPrettyPrinting() //對json結(jié)果格式化.
.setVersion(1.0)
.disableHtmlEscaping()//默認是GSON把HTML 轉(zhuǎn)義的荒吏,但也可以設置不轉(zhuǎn)義
.serializeNulls()//把null值也轉(zhuǎn)換,默認是不轉(zhuǎn)換null值的渊鞋,可以選擇也轉(zhuǎn)換,為空時輸出為{a:null}绰更,而不是{}
.create();
泛型
如果需要轉(zhuǎn)換的類包括泛型,那么也需要用到TypeToken锡宋,通過這個類可以獲取具體的類型
publicclass ApiResult<T> {
privateint ret;
private String msg;
private T data;
publicint getRet() {
return ret;
}
publicvoid setRet(int ret) {
this.ret = ret;
}
public String getMsg() {
return msg;
}
publicvoid setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
publicvoid setData(T data) {
this.data = data;
}
}
ApiResult<UserInfo> r = GsonUtils.parse(json, new TypeToken<ApiResult<UserInfo>>() {}.getType());
解析JsonArray
以前不知道Gson可以解析JsonArray.所以使用了如下方法儡湾,想想真是無知
public static <T> List<T> readJsonArray(JSONArray array, Class<T> entityType){
Gson gson =new Gson();
List<T> list = new ArrayList<>();
for(int i=0;i<array.length();i++){
try {
T t = gson.fromJson(array.getJSONObject(i).toString(),entityType);
list.add(t);
} catch (JSONException e) {
e.printStackTrace();
}
}
return list;
}
以下是gson user guideu中的內(nèi)容:
Array Examples
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"abc", "def", "ghi"};
// Serialization
gson.toJson(ints); // ==> [1,2,3,4,5]
gson.toJson(strings); // ==> ["abc", "def", "ghi"]
// Deserialization
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
// ==> ints2 will be same as ints
We also support multi-dimensional arrays, with arbitrarily complex element types.
Collections Examples
Gson gson = new Gson();
Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);
// Serialization
String json = gson.toJson(ints); // ==> json is [1,2,3,4,5]
// Deserialization
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
// ==> ints2 is same as ints
Fairly hideous: note how we define the type of collection. Unfortunately, there is no way to get around this in Java.
Collections Limitations
Can serialize collection of arbitrary objects but can not deserialize from it
Because there is no way for the user to indicate the type of the resulting object
While deserializing, Collection must be of a specific generic type
All of this makes sense, and is rarely a problem when following good Java coding practices.