Gson的使用

【前言】最近項(xiàng)目中對數(shù)據(jù)的解析都使用了Gson,艸蛋的是每次都要手寫JavaBean對象很麻煩入愧。抱著能否簡化的心態(tài)閱讀了Gson的部分源碼贬堵。發(fā)現(xiàn)很多以前沒有注意到的知識點(diǎn)划纽。

寫在前面的話

Gson是一個(gè)Java庫拗窃,可用于將Java對象轉(zhuǎn)換為JSON表示瞎领。它也可以用來將JSON字符串轉(zhuǎn)換為等效的Java對象。 Gson可以使用任意Java對象随夸,包括您沒有源代碼的預(yù)先存在的對象九默。

如何生成Json
JsonObject jsonObject = new JsonObject();
JsonObject jsonArray = new JsonObject();

//addProperty():產(chǎn)生JsonObject
jsonObject.addProperty("testString","7c");
jsonObject.addProperty("testInt",7);
jsonObject.addProperty("testBoolean",true);
jsonObject.addProperty("testCharater","7c");

jsonArray.addProperty("testStringArray","7c");
jsonArray.addProperty("testIntArray",7);
jsonArray.addProperty("testBooleanArray",true);

jsonObject.add("JsonElement",jsonArray);
System.out.println(jsonObject.toString());
//Json結(jié)構(gòu)
{
    "JsonElement": {
        "testBooleanArray": true,
        "testIntArray": 7,
        "testStringArray": "7c"
    },
    "testBoolean": true,
    "testCharater": "7c",
    "testInt": 7,
    "testString": "7c"
}
手動解析Json
try {
            JSONObject originJson = new JSONObject(json);
            ManualresolutionBean manualresolutionBean = new ManualresolutionBean();
            boolean success = originJson.optBoolean("success");
            int failCode = originJson.optInt("failCode");
            JSONArray data = originJson.optJSONArray("data");

            List<ManualresolutionBean.JsonList> jsonLists = new ArrayList();
            manualresolutionBean.setFailCode(failCode);
            manualresolutionBean.setSuccess(success);
            for (int i = 0 ; i < data.length() ; i ++){
                JSONObject jsonObject1 = data.getJSONObject(i);
                JsonList jsonList = new JsonList();
                String check = jsonObject1.optString("check");
                String id = jsonObject1.optString("id");
                int isPoor = jsonObject1.optInt("isPoor");
                String level = jsonObject1.optString("level");
                String model = jsonObject1.optString("model");
                String name = jsonObject1.optString("name");
                String pid = jsonObject1.optString("pid");
                String sort = jsonObject1.optString("sort");
                String supportPoor = jsonObject1.optString("supportPoor");

                jsonList.setCheck(check);
                jsonList.setId(id);
                jsonList.setIsPoor(isPoor);
                jsonList.setLevel(level);
                jsonList.setModel(model);
                jsonList.setName(name);
                jsonList.setPid(pid);
                jsonList.setSort(sort);
                jsonList.setSupportPoor(supportPoor);
                jsonLists.add(jsonList);
            }
            manualresolutionBean.setList(jsonLists);
        } catch (JSONException e) {
            e.printStackTrace();
        }
}
解析圖.JPG

【注意】
1.藍(lán)色標(biāo)記部分手動解析的時(shí)候充當(dāng)JSONObject;【】充當(dāng)JSONArray宾毒。
2.如果你放在main函數(shù)中執(zhí)行會報(bào) java.lang.RuntimeException: Stub!驼修。這是因?yàn)槟阍贘ava中使用Android包出錯。

通過構(gòu)造器來創(chuàng)建Gson

new Gson()是我們?nèi)粘i_發(fā)中經(jīng)常用來解析數(shù)據(jù)的方式诈铛。熟悉的人員請繞過這部分乙各。

String jsonArray = "[\"U\",\"A\",\"R\",\"T\"]";

Gson gson = new Gson();

 //json與數(shù)組的轉(zhuǎn)換

//json轉(zhuǎn)換為數(shù)組
String[] strings = gson.fromJson(jsonArray, String[].class);
for (String string : strings){
       System.out.println(string);
 }
//數(shù)組轉(zhuǎn)換為json
String s = gson.toJson(strings);
System.out.println(s);
System.out.println("=================================");
//json轉(zhuǎn)換為List
 //new TypeToken<List<String>>(){}.getType()這里為什么需要一個(gè){},查看TypeToken源碼可以發(fā)現(xiàn)
 //這樣一段話TypeToken<List<String>> list = new TypeToken<List<String>>() {};
List<String> list = gson.fromJson(jsonArray, new TypeToken<List<String>>() {
        }.getType());
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
      String next = iterator.next();
      System.out.println(next);
}
//List轉(zhuǎn)換為json
String listJson = gson.toJson(list,new TypeToken<List<String>>() {
        }.getType());
System.out.println(listJson);

Gson用法進(jìn)階

屬性重命名
  • 場景:服務(wù)端返回的字段名癌瘾,與我們本地的字段名有出入觅丰。
  • 原理及用法:@SerializedName 指示此成員的注釋應(yīng)該以提供的名稱值作為其字段名稱序列化為JSON饵溅。
    @SerializedName("name") String a;
    @SerializedName(value="name1", alternate={"name2", "name3"}) String b;
@SerializedName(value ="name",alternate = {"userName","Name","Kobe"})
public String name;

String json =  "{\"name\": \"Uart\"}";
String json1 =  "{\"userName\": \"Uart\"}";
String json2 =  "{\"Name\": \"Uart\"}";
String json3 =  "{\"Kobe\": \"Uart\"}";

Gson gson = new Gson();
User user = gson.fromJson(json,new TypeToken<User>(){}.getType());
User user1 = gson.fromJson(json1,new TypeToken<User>(){}.getType());
User user2 = gson.fromJson(json2,new TypeToken<User>(){}.getType());
User user3 = gson.fromJson(json3,new TypeToken<User>(){}.getType());
user.toString();
user1.toString();
user2.toString();
user3.toString();

字段過濾

基于@Expose注解
  • 原理:指示此成員的注釋應(yīng)公開給JSON序列化或反序列化妨退。
  • 注意 :此注釋要生效必須調(diào)用GsonBuilder的excludeFieldsWithoutExposeAnnotation()方法。
  • 用法:
    @Expose private String firstName;
    @Expose(serialize = false) private String lastName;
    @Expose (serialize = false, deserialize = false) private String emailAddress;
    private String password;
@Expose(serialize = true, deserialize = true)   //序列化和反序列化都生效
private String a;

@Expose(serialize = false, deserialize = true)  //序列化時(shí)不生效蜕企,反序列化時(shí)生效
private String b;

@Expose(serialize = true, deserialize = false)  //序列化時(shí)生效咬荷,反序列化時(shí)不生效
private String c;

@Expose(serialize = false, deserialize = false) //序列化和反序列化都不生效,和不寫注解一樣
private String d;

private String e;

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
FilterBean filterBean = new FilterBean("A", "B", "C", "D", "E");

//序列化
System.out.println(gson.toJson(filterBean));

//反序列化
String json = "{\"a\":\"A\",\"b\":\"B\",\"c\":\"C\",\"d\":\"D\",\"e\":\"E\"}";
FilterBean filterBean1 = gson.fromJson(json, FilterBean.class);
System.out.println(filterBean1.toString());

//輸出結(jié)果
{"a":"A","c":"C"}
FilterBean{a='A', b='B', c='null', d='null', e='null'}
基于版本
  • 原理:@Since自成員或類型出現(xiàn)以來表示版本號的注釋轻掩。
    @Until表示直到成員或類型應(yīng)該存在的版本號的注釋幸乒。
    此注釋對于管理Web服務(wù)的Json類的版本控制非常有用。
  • 注意:此注釋要生效必須調(diào)用GsonBuilder的setVersion(double)方法唇牧。
  • 用法:
    @Since(1.0) private String emailAddress罕扎;
    @Until(1.1) private String emailAddress;
@Since(1.3)
private String a;

@Until(1.9)
private String b;

@Since(1.5)
private String c;

@Until(1.2)
private String d;

private String e;

Gson gson = new GsonBuilder().setVersion(1.3).create();
FilterBean filterBean = new FilterBean("A", "B", "C", "D", "E");

//序列化
System.out.println(gson.toJson(filterBean));

//反序列化
String json = "{\"a\":\"A\",\"b\":\"B\",\"c\":\"C\",\"d\":\"D\",\"e\":\"E\"}";
FilterBean filterBean1 = gson.fromJson(json, FilterBean.class);
System.out.println(filterBean1.toString());

//輸出結(jié)果
{"a":"A","b":"B","e":"E"}
FilterBean{a='A', b='B', c='null', d='null', e='E'}
基于訪問修飾符
  • 原理:excludeFieldsWithModifiers()方法丐重,配置Gson以排除所有具有指定修飾符的類字段腔召。默認(rèn),Gson將排除所有標(biāo)記為瞬態(tài)(transient)或靜態(tài)(static)的字段扮惦。此方法將覆蓋該行為臀蛛。
public String publicField = "public";

protected String protectedField = "protected";

private String privateField = "private";

String defaultField = "default";

final String finalField = "final";

static String staticField = "static";

Gson gson2 = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PRIVATE, Modifier.PUBLIC).create();
ModifierBean modifierBean = new ModifierBean();
System.out.println(gson2.toJson(modifierBean));

//輸出結(jié)果
{"protectedField":"protected","defaultField":"default","finalField":"final","staticField":"static"}
基于策略
  • 原理:GsonBuilder 類包含 setExclusionStrategies(ExclusionStrategy... strategies)方法用于傳入不定長參數(shù)的策略方法,用于直接排除指定字段名或者指定字段類型。
private String stringField;

private int intField;

private double doubleField;

public StrategiesBean(String stringField, int intField, double doubleField) {
        this.stringField = stringField;
        this.intField = intField;
        this.doubleField = doubleField;
}

Gson gson3 = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
//排除指定字段名
return f.getName().equals("stringField");
 }

 @Override
public boolean shouldSkipClass(Class<?> clazz) {
//排除指定字段類型
return clazz.getName().equals(double.class.getName()); }}).create();

StrategiesBean strategies = new StrategiesBean("stringField", 111, 11.22);
System.out.println();
System.out.println(gson3.toJson(strategies));

String json2 = "{\"stringField\":\"stringField\",\"intField\":111,\"doubleField\":11.22}";
strategies = gson3.fromJson(json2, StrategiesBean.class);
System.out.println();
System.out.println(strategies);

//輸出結(jié)果
{"intField":111}

Strategies{stringField='null', intField=111, doubleField=0.0}

感興趣的小伙伴可以研究一下setFieldNamingStrategy()浊仆、addDeserializationExclusionStrategy()客峭、addSerializationExclusionStrategy()這三種方法

自定義配置

輸出null

對于 Gson 而言,在序列化時(shí)如果某個(gè)屬性值為 null 的話抡柿,那么在序列化時(shí)該字段不會參與進(jìn)來舔琅,如果想要顯示輸出該字段的話,可以通過 GsonBuilder 進(jìn)行配置洲劣。

Gson gson3 = new GsonBuilder()
                .serializeNulls()
                .create();

StrategiesBean strategies = new StrategiesBean(null, 111, 11.22);
System.out.println();
System.out.println(gson3.toJson(strategies));
//輸出結(jié)果
{"stringField":null,"intField":111,"doubleField":11.22}
格式化輸出Json

Gson gson3 = new GsonBuilder()
.serializeNulls()
.setPrettyPrinting()//格式化輸出
.create();

StrategiesBean strategies = new StrategiesBean(null, 111, 11.22);
System.out.println();
System.out.println(gson3.toJson(strategies));
//輸出結(jié)果
{
"stringField": null,
"intField": 111,
"doubleField": 11.22
}

TypeAdapter

  • 作用:將Java對象與JSON進(jìn)行轉(zhuǎn)換搏明。默認(rèn)情況下,Gson使用其內(nèi)置類型將應(yīng)用程序類轉(zhuǎn)換為JSON適配器闪檬。如果Gson的默認(rèn)JSON轉(zhuǎn)換不適合某種類型星著,擴(kuò)展此類以定制轉(zhuǎn)換。
序列化交換位置
@Override
public void write(JsonWriter out, UartBean value) throws IOException {
        //序列化過程
        if(value == null) {
            out.nullValue();
            return;
        }
        String name = value.getName();
        int age = value.getAge();
        value.setName(age + "");
        value.setAge(Integer.valueOf(name));
        out.value(value.getName());
        out.value(value.getAge());
    }

@Override
public UartBean read(JsonReader in) throws IOException {
        //反序列化過程
        if(in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        in.beginObject();
        UartBean uartBean = new UartBean();
        while(in.hasNext()) {
            switch (in.nextName()) {
                case "name" :
                    uartBean.setName(in.nextString());
                    break;
                case "age":
                    uartBean.setAge(in.nextInt());
                    break;
            }
        }
        in.endObject();
        return uartBean;
    }

Gson gson4 = new GsonBuilder().registerTypeAdapter(UartBean.class, new UartAdapter()).create();
UartBean uartBean = new UartBean("10", 20);
System.out.println(gson4.toJson(uartBean));

String json4 = "{\"name\":\"10\",\"age\":24}";
UartBean bean = gson4.fromJson(json4, UartBean.class);
System.out.println();
System.out.println(bean);

//輸出結(jié)果
"20" 10
UartBean{name='10', age=24}

JsonSerializer 和 JsonDeserializer是TypeAdapter提供的專門針對序列化和反序列化的接口粗悯。感興趣的朋友可以自行了解一下虚循。

更新

 "156": "42F7B18E9C12ACFDC1B9",
 "156": "3247F56244FDE",

針對上述json字符串如何解析?

stationNameInfoList = new ArrayList<EquivalentStationNameInfo>();
        Iterator<String> keys = object.keys();

        while (keys.hasNext()) {
            EquivalentStationNameInfo equivalentStationNameInfo = new EquivalentStationNameInfo();
            String next = keys.next();
            equivalentStationNameInfo.setStationName(next);
            equivalentStationNameInfo.setStationId(object.optString(next));
            for (EquivalentHourInfo info : equivalentHourInfoList) {
                if (info.getStationName().equals(next)) {
                    stationNameInfoList.add(equivalentStationNameInfo);
                }
            }

        }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末样傍,一起剝皮案震驚了整個(gè)濱河市横缔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衫哥,老刑警劉巖茎刚,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異撤逢,居然都是意外死亡膛锭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門蚊荣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來初狰,“玉大人,你說我怎么就攤上這事互例∩萑耄” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵媳叨,是天一觀的道長腥光。 經(jīng)常有香客問我,道長糊秆,這世上最難降的妖魔是什么武福? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮扩然,結(jié)果婚禮上艘儒,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好界睁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布觉增。 她就那樣靜靜地躺著,像睡著了一般翻斟。 火紅的嫁衣襯著肌膚如雪逾礁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天访惜,我揣著相機(jī)與錄音嘹履,去河邊找鬼。 笑死债热,一個(gè)胖子當(dāng)著我的面吹牛砾嫉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窒篱,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼焕刮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了墙杯?” 一聲冷哼從身側(cè)響起配并,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎高镐,沒想到半個(gè)月后溉旋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嫉髓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年观腊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岩喷。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恕沫,死狀恐怖监憎,靈堂內(nèi)的尸體忽然破棺而出纱意,到底是詐尸還是另有隱情,我是刑警寧澤鲸阔,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布偷霉,位于F島的核電站,受9級特大地震影響褐筛,放射性物質(zhì)發(fā)生泄漏类少。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一渔扎、第九天 我趴在偏房一處隱蔽的房頂上張望硫狞。 院中可真熱鬧,春花似錦、人聲如沸残吩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泣侮。三九已至即彪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間活尊,已是汗流浹背隶校。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蛹锰,地道東北人深胳。 一個(gè)月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像铜犬,于是被迫代替她去往敵國和親稠屠。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

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

  • 關(guān)于json翎苫,gson是最常用到的一個(gè)庫权埠。平常使用時(shí)我通常使用Gson gson = new Gson();的方式...
    黑泥卡閱讀 10,071評論 1 14
  • 1.概述2.Gson的目標(biāo)3.Gson的性能和擴(kuò)展性4.Gson的使用者5.如何使用Gson 通過Maven來使用...
    人失格閱讀 14,223評論 2 18
  • Android中Gson的使用 1 簡介 Gson是一個(gè)Java庫,作用是將Java對象轉(zhuǎn)換成它對應(yīng)的JSON表示...
    LuckyXiang閱讀 19,891評論 2 3
  • 本文為作者根據(jù)日常使用結(jié)合Gson源碼注釋及wiki所作的原創(chuàng)內(nèi)容煎谍,轉(zhuǎn)載請注明出處攘蔽。 該系列其它文章 你真的會用G...
    怪盜kidou閱讀 61,164評論 67 141
  • 今天婆婆又在飯桌上當(dāng)著大家的面教育兒子,我急忙喊媽媽呐粘,媽媽满俗,你吃這個(gè)。我媽媽最愛機(jī)會教育作岖,孩子高高興興的的...
    富足喜悅的二小姐閱讀 167評論 3 4