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":10086,"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:com.yaojt.sdk.java.gsonReflect.MainGsonReflect$1@67117f44

        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:com.google.gson.stream.JsonWriter@12bc6874
    }

上面我只打印出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:com.google.gson.stream.JsonWriter@18ef96
    }

总结

好了,上面就是几个具有代表性的方法的讲解。功能还是很强大的,我们可以边学便用,可以更好的使用它。如果我们再对Writer和JsonElement接口及其子类学习的话,那么我们的功力就会更上一层楼。共勉!

如有任何问题,请及时与我联系。谢谢。