gson的使用細節(jié)

關于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.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市执俩,隨后出現(xiàn)的幾起案子徐钠,更是在濱河造成了極大的恐慌,老刑警劉巖役首,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丹皱,死亡現(xiàn)場離奇詭異,居然都是意外死亡宋税,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門讼油,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杰赛,“玉大人,你說我怎么就攤上這事矮台》ν停” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵瘦赫,是天一觀的道長辰晕。 經(jīng)常有香客問我,道長确虱,這世上最難降的妖魔是什么含友? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上窘问,老公的妹妹穿的比我還像新娘辆童。我一直安慰自己,他們只是感情好惠赫,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布把鉴。 她就那樣靜靜地躺著,像睡著了一般儿咱。 火紅的嫁衣襯著肌膚如雪庭砍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天混埠,我揣著相機與錄音怠缸,去河邊找鬼。 笑死岔冀,一個胖子當著我的面吹牛凯旭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播使套,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼罐呼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了侦高?” 一聲冷哼從身側(cè)響起嫉柴,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奉呛,沒想到半個月后计螺,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡瞧壮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年登馒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咆槽。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡陈轿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出秦忿,到底是詐尸還是另有隱情麦射,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布灯谣,位于F島的核電站潜秋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胎许。R本人自食惡果不足惜峻呛,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一罗售、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杀饵,春花似錦莽囤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谜悟,卻和暖如春话肖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背葡幸。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工最筒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蔚叨。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓床蜘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蔑水。 傳聞我的和親對象是個殘疾皇子邢锯,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容