天天看點

Android之gson操作系列2之tojson

Android之gson操作系列2之tojson

文章連結:

知識點

  1. tojson各方法簡介;
  2. 新名詞記錄{TypeToken:使用者擷取類的類型的類;Appendable:向一個對象追加資料的接口;Writer:對char資料流寫入資料的接口;JsonWriter:Writer的實作類}

概述

gson的功能很是強大的,但是大多數人都隻是用來最簡單實用的幾個初級功能,但是幾個初級的功能已經是能夠面對大部分的需求了。不能怪我們,隻能說Google封裝的太好了。其實還有很多的進階功能可以去學習看看。本文隻是針對tojson序列化方法來說,如果再加上fromjson的話,篇幅就有點過長了。下一篇文章我會講fromjson。

gson.tojson()一共有一下8個,如下所示。這裡挑有代表性的來說明。

//有傳回值
public String toJson(JsonElement jsonElement)
public String toJson(Object src)
public String toJson(Object src, Type typeOfSrc)
//無傳回值
public void toJson(Object src, Appendable writer)
public void toJson(Object src, Type typeOfSrc, Appendable writer)
public void toJson(Object src, Type typeOfSrc, JsonWriter writer)
public void toJson(JsonElement jsonElement, Appendable writer)
public void toJson(JsonElement jsonElement, JsonWriter writer)
           

我們用的最常的就是toJson(Object src)方法。這個方法是序列化确定類型的字元串生成json。所謂的确定是在這個方法裡面會調用src.getClass()來擷取到傳入的Object對應的類型type,但是這個方法會擦除Java類的特性,進而得不到此類的資訊。下面是其用法:

Gson gson = new Gson();
        String StrToJson = gson.toJson(userBean);
        System.out.println("序列化操作結果:" + StrToJson);
        //序列化操作結果:{"id":,"nickName":"yaojt"}
           

toJson(Object src, Type typeOfSrc)方法。對于第二個參數,我們可以根據TypeToken擷取到類的類型。

TypeToken的使用非常簡單,隻要将需要擷取類型的泛型類作為TypeToken的泛型參數構造一個匿名的子類,就可以通過getType()方法擷取到我們使用的泛型類的泛型參數類型。代碼如下:

public void gsonSerieal1() {
        BaseCat<String> baseCat = new BaseCat<>();
        baseCat.setCategory("yaojt");
        Type type = new TypeToken<BaseCat<String>>() {
        }.getType();
        System.out.println("type: " + type);
        //type: com.yaojt.sdk.java.gsonReflect.BaseCat<java.lang.String>
        Gson gson = new Gson();
        String result = gson.toJson(baseCat, type);
        System.out.println("result: " + result);
        //result: {"category":"yaojt"}
    }
           

public void toJson(Object src, Appendable writer)。第一個參數不說了。對于第二個參數該怎麼了解呢,我們注意到這個方法是沒有傳回值的。我天,那麼我轉換之後想要的值哪裡去了???難道不給回我們了嗎?

當然不是,我們暫且不管Appendable這個類,光是看形參的命名writer,就是作者?作者就是輸出文字的。是以我們可以猜想,這個對象可能就是作為輸出的。點進去看源碼的解釋,果然是如此,在序列化的值,Google幫我們寫入到Appendable這個參數裡面。

那麼,我們有必要先了解一下Appendable是何方神聖?

Appendable是一個接口,裡面有3個方法,如下:

Appendable append(char c) 向此 Appendable 添加指定字元。

Appendable append(CharSequence csq) 向此 Appendable 添加指定的字元序列。

Appendable append(CharSequence csq, int start, int end) 向此 Appendable 添加指定字元序列的子序列。

看了解釋,我們知道他其實就是一個追加char/CharSequence值的功能嘛,這好辦,我們直接使用實作它的子類就應該OK了。但是這個接口被誰實作了呢?

已知的實作類有BufferedWriter, CharArrayWriter, CharBuffer, FileWriter, FilterWriter, LogStream, OutputStreamWriter, PipedWriter, PrintStream, PrintWriter, StringBuffer, StringBuilder, StringWriter, Writer。

既然有這麼多,我們就選擇Appendable原始接口和StringBuilder子類來看看怎麼實作呗。

首先實作一個Appendable接口,然後我在其中兩個方法追加了值,然後tojson之後,列印出來,可以看到列印出的是這個對象的哈希碼,無法看到裡面的具體的值。

另外一個就是StringBuilder對象,我在這裡先放入了一個“初始值。”,然後在作為tojson的第二個參數傳入,列印日志的結果果然是在StringBuilder對象後面追加了序列化之後的值。那麼這樣的話,如何使用的想象空間就大了。

下面我們看代碼

public void gsonSerieal2() {
        Gson gson = new Gson();
        BaseCat<String> baseCat = new BaseCat<>();
        baseCat.setCategory("yaojt");
        final Appendable appendable = new Appendable() {
            @Override
            public Appendable append(CharSequence csq) throws IOException {
                return null;
            }
            @Override
            public Appendable append(CharSequence csq, int start, int end) throws IOException {
                return this.append("2." + csq + ", ");
            }
            @Override
            public Appendable append(char c) throws IOException {
                return this.append("3." + c + ", ");
            }
        };

        gson.toJson(baseCat, System.out);
        //{"category":"yaojt"}

        //appendable是一個接口,3個方法,都是使用者像一個對象裡面追加數值
        //将序列化後的值,追加到appendable裡面去
        gson.toJson(baseCat, appendable);
        System.out.append("appendable:" + appendable.toString());
        //appendable:[email protected]

        StringBuilder stringBuilder = new StringBuilder("初始值。");
        //将序列化後的值,追加到stringBuilder裡面去。
        gson.toJson(baseCat, stringBuilder);
        System.out.append("stringBuilder:" + stringBuilder.toString());
        //初始值。{"category":"yaojt"}
    }
           

public void toJson(Object src, Type typeOfSrc, JsonWriter writer)這個方法也也是沒有傳回值的,是以也需要傳入一個參數來接受轉換結果。參數1不講了,參數2type類型上面已經講了,現在隻要關注第三個參數,他也是用來接受序列化的結果。

跟蹤源碼,可以看到它也是實作了Writer接口,用來進行生成json的。因為本文講的不是這方向,是以不深入了,有興趣的童鞋可以深入去了解。

然後這個方法的使用如下:

public void gsonSerieal3() {
        StringWriter stringWriter = new StringWriter();
        JsonWriter jsonWriter = new JsonWriter(stringWriter);
        BaseCat<String> baseCat = new BaseCat<>();
        baseCat.setCategory("tanksu");
        Gson gson = new Gson();
        Type type = new TypeToken<BaseCat<String>>() {
        }.getType();
        gson.toJson(baseCat, type, jsonWriter);
        System.out.println("jsonWriter:" + jsonWriter.getSerializeNulls());
        //jsonWriter:[email protected]
    }
           

上面我隻列印出jsonWriter的哈希碼,實際上我們可以對jsonWriter對象進行操作,以獲得我們需要的結果。

public void toJson(JsonElement jsonElement, JsonWriter writer)方法。此方法無傳回值,我們着重看第一個參數JsonElement。

JsonElement是一個抽象類,代表的是json的元素。它的已知子類有JsonNull、JsonObject、JsonArray、JsonPrimitive等。由于範疇原因,我在這裡也不詳述這個了。這隻是一個入參,我們關注的應該是結果的出參,第二個參數。

下面給出代碼:

public void gsonSerieal4() {
        StringWriter stringWriter = new StringWriter();
        JsonWriter jsonWriter = new JsonWriter(stringWriter);
        BaseCat<String> baseCat = new BaseCat<>();
        baseCat.setCategory("tanksu");
        Gson gson = new Gson();
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("property", "value");
        gson.toJson(jsonObject, jsonWriter);
        System.out.println("jsonWriter:" + jsonWriter);
        //jsonWriter:[email protected]
    }
           

總結

好了,上面就是幾個具有代表性的方法的講解。功能還是很強大的,我們可以邊學便用,可以更好的使用它。如果我們再對Writer和JsonElement接口及其子類學習的話,那麼我們的功力就會更上一層樓。共勉!

如有任何問題,請及時與我聯系。謝謝。