美文网首页android开发杂识JavaIT相关
你真的会用Gson吗?Gson使用指南(二)

你真的会用Gson吗?Gson使用指南(二)

作者: 怪盗kidou | 来源:发表于2016-04-01 17:31 被阅读42943次

本文为作者根据日常使用结合Gson源码注释及wiki所作的原创内容,转载请注明出处。

该系列其它文章

注:此系列基于Gson 2.4。

上一篇文章 你真的会用Gson吗?Gson使用指南(一) 我们了解了Gson的基础用法,这次我们继续深入了解Gson的使用方法。

本次的主要内容:

  • Gson的流式反序列化
  • Gson的流式序列化
  • 使用GsonBuilder导出null值、格式化输出、日期时间及其它小功能

一、Gson的流式反序列化

自动方式

Gson提供了fromJson()toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。同时每个方法都提供了重载方法,我常用的总共有5个。

这是我在上一篇文章开头说的,但我到最后也一直没有是哪5个,这次我给列出来之后,你就知道这次讲的是哪个了。

Gson.toJson(Object);
Gson.fromJson(Reader,Class);
Gson.fromJson(String,Class);
Gson.fromJson(Reader,Type);
Gson.fromJson(String,Type);

好了,本节结束!

看第2、4行,Reader懂了吧

手动方式
手动的方式就是使用stream包下的JsonReader类来手动实现反序列化,和Android中使用pull解析XML是比较类似的。

String json = "{\"name\":\"怪盗kidou\",\"age\":\"24\"}";
User user = new User();
JsonReader reader = new JsonReader(new StringReader(json));
reader.beginObject(); // throws IOException
while (reader.hasNext()) {
    String s = reader.nextName();
    switch (s) {
        case "name":
            user.name = reader.nextString();
            break;
        case "age":
            user.age = reader.nextInt(); //自动转换
            break;
        case "email":
            user.email = reader.nextString();
            break;
    }
}
reader.endObject(); // throws IOException
System.out.println(user.name);  // 怪盗kidou
System.out.println(user.age);   // 24
System.out.println(user.email); // ikidou@example.com

其实自动方式最终都是通过JsonReader来实现的,如果第一个参数是String类型,那么Gson会创建一个StringReader转换成流操作。

Gson流式解析

二、Gson的流式序列化

自动方式

Gson.toJson方法列表

所以啊,学会利用IDE的自动完成是多么重要这下知道了吧!
可以看出用红框选中的部分就是我们要找的东西。

提示:PrintStream(System.out) 、StringBuilderStringBuffer*Writer都实现了Appendable接口。

Gson gson = new Gson();
User user = new User("怪盗kidou",24,"ikidou@example.com");
gson.toJson(user,System.out); // 写到控制台

手动方式

JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));
writer.beginObject() // throws IOException
        .name("name").value("怪盗kidou")
        .name("age").value(24)
        .name("email").nullValue() //演示null
        .endObject(); // throws IOException
writer.flush(); // throws IOException
//{"name":"怪盗kidou","age":24,"email":null}

提示:除了beginObjectendObject还有beginArrayendArray,两者可以相互嵌套,注意配对即可。beginArray后不可以调用name方法,同样beginObject后在调用value之前必须要调用name方法。

三、 使用GsonBuilder导出null值、格式化输出、日期时间

一般情况下Gson类提供的 API已经能满足大部分的使用场景,但我们需要更多更特殊、更强大的功能时,这时候就引入一个新的类 GsonBuilder

GsonBuilder从名上也能知道是用于构建Gson实例的一个类,要想改变Gson默认的设置必须使用该类配置Gson。

GsonBuilder用法

Gson gson = new GsonBuilder()
               //各种配置
               .create(); //生成配置好的Gson

Gson在默认情况下是不动导出值null的键的,如:

public class User {
    //省略其它
    public String name;
    public int age;
    public String email;
}
Gson gson = new Gson();
User user = new User("怪盗kidou",24);
System.out.println(gson.toJson(user)); //{"name":"怪盗kidou","age":24}

可以看出,email字段是没有在json中出现的,当我们在调试是、需要导出完整的json串时或API接中要求没有值必须用Null时,就会比较有用。

使用方法:

Gson gson = new GsonBuilder()
        .serializeNulls()
        .create();
User user = new User("怪盗kidou", 24);
System.out.println(gson.toJson(user)); //{"name":"怪盗kidou","age":24,"email":null}

格式化输出、日期时间及其它

这些都比较简单就不一一分开写了。

Gson gson = new GsonBuilder()
        //序列化null
        .serializeNulls()
        // 设置日期时间格式,另有2个重载方法
        // 在序列化和反序化时均生效
        .setDateFormat("yyyy-MM-dd")
        // 禁此序列化内部类
        .disableInnerClassSerialization()
        //生成不可执行的Json(多了 )]}' 这4个字符)
        .generateNonExecutableJson()
        //禁止转义html标签
        .disableHtmlEscaping()
        //格式化输出
        .setPrettyPrinting()
        .create();

注意:内部类(Inner Class)和嵌套类(Nested Class)的区别

这次文章就到这里,欢迎提问互动,如有不对的地方请指正。

下篇文章内容提要

  • 字段过滤的几种方法
    • 基于@Expose注解
    • 基于访问修饰符
    • 基于版本
    • 自定义规则
  • POJO与JSON的字段映射规则

相关文章

网友评论

  • 杨晓是大V:越看越喜欢
    怪盗kidou:@virusbam 😜
  • 可乐_JS:棒棒哒啦
  • wmjwmj:皮这一下开心吗
  • luckbing:赞,学习了,谢谢楼主啦:relaxed:
  • 紫木冰枫:setDateFormat("yyyy-MM-dd")
    不生效。
    怪盗kidou:@紫木冰枫 :sweat_smile: ,先不说long不是为表示时间而存在的,我问你两个问题:
    1、用long来表示时间时单位是啥,亳秒还是该用unix时间戳的秒?
    2、排除第一问,long l = gson.fromJson("20170906",long.class); 你觉得应该得多少? 就是字面的20170906,还是该得表示时间的 1504627200 ?
    紫木冰枫:@怪盗kidou 对long不生效,对date生效。
    怪盗kidou:会生效
  • 紫木冰枫:这有什么用?
  • 壹公升:我就想弱弱的问一句内部类和嵌套类的区别是什么
  • 放开那芒果:Gson gson = new Gson();
    User user = new User("怪盗kidou",24,"ikidou@example.com");
    gson.toJson(user,System.out); // 写到控制台
    单独这样写怎么没见在控制台上输出呢?
    f954933b17ac:@放开那芒果 我也遇到同样的问题,刷新没用啊
    放开那芒果:不好意思,是我自己没刷新。。。。
  • 放开那芒果:发现个问题,String json = "{\"name\":\"怪盗kidou\",\"age\":\"24\"}";
    User user = new User();
    JsonReader reader = new JsonReader(new StringReader(json));
    reader.beginObject(); // throws IOException
    while (reader.hasNext()) {
    String s = reader.nextName();
    switch (s) {
    case "name":
    user.name = reader.nextString();
    break;
    case "age":
    user.age = reader.nextInt(); //自动转换
    break;
    case "email":
    user.email = reader.nextString();
    break;
    }
    }
    reader.endObject(); // throws IOException
    System.out.println(user.name); // 怪盗kidou
    System.out.println(user.age); // 24
    System.out.println(user.email); // ikidou@example.com

    这里要是用@SerializedName(value = "emailAddress", alternate = { "email_address",
    "email" })会爆炸
    放开那芒果:@怪盗kidou 还有
    Gson gson = new Gson();
    User user = new User("怪盗kidou",24,"ikidou@example.com");
    gson.toJson(user,System.out); // 写到控制台
    单独这样写怎么没见在控制台上输出呢?把他全部写完才输出,而且输出两条
    放开那芒果:@怪盗kidou 就是会崩溃,获取不到值,@SerializedName(value = "emailAddress", alternate = { "email_address",
    "email" })
    public String emailAddress;
    怪盗kidou:@放开那芒果 会爆炸?什么意思
  • 4b760e12eaf8:JDK7下发现PrintStream 和Writer才是实现了Appendable接口,OutputStream没有实现
    怪盗kidou:@iceblock 感谢指正:+1:
  • 仁昌居士:请问,禁止序列化内部类有什么用处?什么情况会需要不序列化内部类,不序列化,不就没必要去建这个内部类啊。
  • 柒月下旬:我的天,就我一个看不懂吗
  • Zack_zhou:谢谢前辈的总结!
  • Neogx:非常好,最近正在为这些东东烦呢!
  • e19752dfa551:“流式”是什么意思啊?是不是一条方法调用链啊?
    e19752dfa551:@怪盗kidou 感谢
    怪盗kidou: @程序猴 不是,说的是解析的时候的数据源是流,不需要你先取出整个json字符串
  • bb500d92fb52:不错,很好理解。
  • Jafir:对于 很多类型是long的时间戳 有用么? 是会自动转化为时间格式么?
    tcgx:@Jafir 需要设置 setDateFormat(DateFormat.LONG)
  • Jafir:第二篇感觉没啥人提问呀,我问一个小问题
    那个builder里面 setDataFormat 那个的具体作用和意思是什么?
  • SingorZhu:不错,又学到东西了
  • mingzikb:感谢分享。

本文标题:你真的会用Gson吗?Gson使用指南(二)

本文链接:https://www.haomeiwen.com/subject/fhzelttx.html