原文:http://www.jianshu.com/p/8cc857583ff4

TypeAdapter介绍

Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。

基本概念

  • Serialization:序列化,使Java对象到Json字符串的过程。
  • Deserialization:反序列化,字符串转换成Java对象。
  • JSON数据中的JsonElement有下面这四种类型:
    JsonPrimitive —— 例如一个字符串或整型
    JsonObject—— 一个以 JsonElement 名字(类型为 String)作为索引的集合。也就是说可以把 JsonObject 看作值为 JsonElement 的键值对集合。
    JsonArray—— JsonElement 的集合。注意数组的元素可以是四种类型中的任意一种,或者混合类型都支持。
    JsonNull—— 值为null

Gson解决的问题

  1. 提供一种像toString()和构造方法的很简单的机制,来实现Java 对象和Json之间的互相转换。

  2. 允许已经存在的无法改变的对象,转换成Json,或者Json转换成已存在的对象。

  3. 允许自定义对象的表现形式

  4. 支持任意的复杂对象

  5. 能够生成可压缩和可读的Json的字符串输出。

Gson处理对象的几个重要点

1 推荐把成员变量都声明称private的

2 没有必要用注解(@Expose 注解)指明某个字段是否会被序列化或者反序列化,所有包含在当前类(包括父类)中的字段都应该默认被序列化或者反序列化

3 如果某个字段被 transient 这个Java关键词修饰,就不会被序列化或者反序列化

4 下面的实现方式能够正确的处理null
1)当序列化的时候,如果对象的某个字段为null,是不会输出到Json字符串中的。
2)当反序列化的时候,某个字段在Json字符串中找不到对应的值,就会被赋值为null

5 如果一个字段是 synthetic
的,他会被忽视,也即是不应该被序列化或者反序列化

6 内部类(或者anonymous class(匿名类),或者local class(局部类,可以理解为在方法内部声明的类))的某个字段和外部类的某个字段一样的话,就会被忽视,不会被序列化或者反序列化


Gson中的一些注解

1 @SerializedName注解

该注解能指定该字段在JSON中对应的字段名称

public class Box {@SerializedName("w")private int width;@SerializedName("h")private int height;@SerializedName("d")private int depth;// Methods removed for brevity
}

也就是说{"w":10,"h":20,"d":30} 这个JSON 字符串能够被解析到上面的width,height和depth字段中。

2 @Expose注解

该注解能够指定该字段是否能够序列化或者反序列化,默认的是都支持(true)。

public class Account {@Expose(deserialize = false)private String accountNumber;@Exposeprivate String iban;@Expose(serialize = false)private String owner;@Expose(serialize = false, deserialize = false)private String address;private String pin;
}

需要注意的通过 builder.excludeFieldsWithoutExposeAnnotation()方法是该注解生效。

  final GsonBuilder builder = new GsonBuilder();builder.excludeFieldsWithoutExposeAnnotation();final Gson gson = builder.create();
3 @Since和@Until注解

Since代表“自从”,Until 代表”一直到”。它们都是针对该字段生效的版本。比如说 @Since(1.2)代表从版本1.2之后才生效,@Until(0.9)代表着在0.9版本之前都是生效的。

public class SoccerPlayer {private String name;@Since(1.2)private int shirtNumber;@Until(0.9)private String country;private String teamName;// Methods removed for brevity
}

也就是说我们利用方法builder.setVersion(1.0)定义版本1.0,如下:

 final GsonBuilder builder = new GsonBuilder();builder.setVersion(1.0);
final Gson gson = builder.create();
final SoccerPlayer account = new SoccerPlayer();account.setName("Albert Attard");account.setShirtNumber(10); // Since version 1.2account.setTeamName("Zejtun Corinthians");account.setCountry("Malta"); // Until version 0.9final String json = gson.toJson(account);System.out.printf("Serialised (version 1.0)%n  %s%n", json);

由于shirtNumbercountry作用版本分别是1.2之后,和0.9之前,所以在这里都不会得到序列化,所以输出结果是:

Serialised (version 1.0){"name":"Albert Attard","teamName":"Zejtun Corinthians"}

Gson 序列化

英文Serialize和format都对应序列化,这是一个Java对象到JSON字符串的过程。
接着看一个例子,下面分别是java类和以及我们期望的JSON数据:

public class Book {private String[] authors;private String isbn10;private String isbn13;private String title;//为了代码简洁,这里移除getter和setter方法等}
{"title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases","isbn-10": "032133678X","isbn-13": "978-0321336781","authors": ["Joshua Bloch","Neal Gafter"]
}

你肯定能发现JSON数据中出现了isbn-10isbn-13, 我们怎么把字段数据isbn10isbn13转化为JSON数据需要的isbn-10isbn-13,Gson当然为我们提供了对应的解决方案

1 序列化方案1

采用上面提到的@SerializedName注解。

public class Book {private String[] authors;@SerializedName("isbn-10")private String isbn10;@SerializedName("isbn-13")private String isbn13;private String title;//为了代码简洁,这里移除getter和setter方法等}
2 序列化方案2

利用JsonSerializer

public class BookSerialiser implements JsonSerializer {@Overridepublic JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) {final JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("title", book.getTitle());
        jsonObject.addProperty("isbn-10", book.getIsbn10());
        jsonObject.addProperty("isbn-13", book.getIsbn13());
final JsonArray jsonAuthorsArray = new JsonArray();
        for (final String author : book.getAuthors()) {final JsonPrimitive jsonAuthor = new JsonPrimitive(author);
            jsonAuthorsArray.add(jsonAuthor);
        }jsonObject.add("authors", jsonAuthorsArray);
return jsonObject;
    }
}

下面对序列化过程进行大致的分析:

  • JsonSerializer是一个接口,我们需要提供自己的实现,来满足自己的序列化要求。

    public interface JsonSerializer<T> {/***Gson 会在解析指定类型T数据的时候触发当前回调方法进行序列化** @param T 需要转化为Json数据的类型,对应上面的Book* @return 返回T指定的类对应JsonElement*/
    public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);
    }
  • 首先在上面的代码中,我们需要创建的是一个JsonElement对象,这里对应Book是一个对象,所以创建一个JsonObject类型。
    final JsonObject jsonObject = new JsonObject();
  • 然后我们将相应字段里面的数据填充到jsonObject里面。
    jsonObject.addProperty...
    jsonObject.add...

    下面是jsonObject中的添加方法:

  • 所以最后返回的还是一个JsonElement 类型,这里对应的是jsonObject。完成了javaBean->JSON数据的转化。

  • 同样需要配置,

    // Configure GSONfinal GsonBuilder gsonBuilder = new GsonBuilder();gsonBuilder.registerTypeAdapter(Book.class, new BookSerialiser());gsonBuilder.setPrettyPrinting();final Gson gson = gsonBuilder.create();final Book javaPuzzlers = new Book();javaPuzzlers.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases");javaPuzzlers.setIsbn10("032133678X");javaPuzzlers.setIsbn13("978-0321336781");javaPuzzlers.setAuthors(new String[] { "Joshua Bloch", "Neal Gafter" });// Format to JSONfinal String json = gson.toJson(javaPuzzlers);System.out.println(json);

    ,这里对应的是
    gsonBuilder.registerTypeAdapter(Book.class, new BookSerialiser())方法进行JsonSerializer的配置。在上面例子中,通过调用gsonBuilder.setPrettyPrinting();方法还告诉了 Gson 对生成的 JSON 对象进行格式化


Gson 反序列化

英文parse和deserialise对应反序列化,这是一个字符串转换成Java对象的过程。
我们同样采用上面一小节的代码片段,只不过现在我们需要做的是将:

{"title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases","isbn-10": "032133678X","isbn-13": "978-0321336781","authors": ["Joshua Bloch","Neal Gafter"]
}

转化为对应的Book实体类,

1 反序列化方案1

利用@SerializedName 注解
也就是说我们的实体类Book.java可以这么写:

public class Book {private String[] authors;@SerializedName("isbn-10")private String isbn10;@SerializedName(value = "isbn-13", alternate = {"isbn13","isbn.13"})private String isbn13;private String title;//为了代码简洁,这里移除getter和setter方法等}

可以看到这里我们在@SerializedName 注解使用了一个value, alternate字段,value也就是默认的字段,对序列化和反序列化都有效,alternate只有反序列化才有效果。也就是说一般服务器返回给我们JSON数据的时候可能同样的一个图片,表示"image","img","icon"等,我们利用@SerializedName 中的alternate字段就能解决这个问题,全部转化为我们实体类中的图片字段。

2 反序列化方案2

我们在序列化的时候使用的是JsonSerialize ,这里对应使用JsonDeserializer
我们将解析到的json数据传递给Book的setter方法即可。

public class BookDeserializer implements JsonDeserializer<Book> {@Overridepublic Book deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)throws JsonParseException {final JsonObject jsonObject = json.getAsJsonObject();final JsonElement jsonTitle = jsonObject.get("title");final String title = jsonTitle.getAsString();final String isbn10 = jsonObject.get("isbn-10").getAsString();final String isbn13 = jsonObject.get("isbn-13").getAsString();final JsonArray jsonAuthorsArray = jsonObject.get("authors").getAsJsonArray();final String[] authors = new String[jsonAuthorsArray.size()];for (int i = 0; i < authors.length; i++) {final JsonElement jsonAuthor = jsonAuthorsArray.get(i);authors[i] = jsonAuthor.getAsString();}final Book book = new Book();book.setTitle(title);book.setIsbn10(isbn10);book.setIsbn13(isbn13);book.setAuthors(authors);return book;}
}

和Gson序列化章节一样,我们这里接着分析我们是怎么将JSON数据解析(反序列化)为实体类的:

  • 因为我们可以发现上面的JSON数据是一个{}大括号包围的,也就意味着这是一个Json对象。所以首先我们通过
    final JsonObject jsonObject = json.getAsJsonObject();将我们的JsonElement转化为JsonObject
  • 通过jsonObject.get("xxx").getAsString()的形式获取相应String的值
  • 通过jsonObject.get("xx").getAsJsonArray();获取相应的json数组,并遍历出其中的相应字段值
  • 通过setter方法,将获取到的值设置给Book类。
  • 最终返回的是 Book的对象实例。完成了JSON->javaBean的转化
  • 同样需要配置
  • 关于从本地流中读取Json数据可以使用 InputStreamReader完成

    // Configure GsonGsonBuilder gsonBuilder = new GsonBuilder();gsonBuilder.registerTypeAdapter(Book.class, new BookDeserializer());Gson gson = gsonBuilder.create();// The JSON datatry(Reader reader = new InputStreamReader(Main.class.getResourceAsStream("/part1/sample.json"), "UTF-8")){// Parse JSON to JavaBook book = gson.fromJson(reader, Book.class);System.out.println(book);}

GSON基本应用【L】相关推荐

  1. Gson应用:利用map和list来拼装Json消息

    Gson应用:利用map和list来拼装Json消息 1 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import ja ...

  2. java lang保_android – Gson中的RuntimeException解析JSON:无法调用受保护的java.lang.ClassLoader()而没有args...

    问题是你试图直接将系统提供的类(Location)转换为JSON.而且,正如您所看到的,在序列化内部状态/ Java特定事物时会遇到问题. JSON是一种传递信息的半通用方式. 查看Location类 ...

  3. FastJSON、Gson和Jackson性能对比

    Java处理JSON数据有三个比较流行的类库FastJSON.Gson和Jackson.本文将测试这三个类库在JSON序列化和反序列化的方面表现,主要测试JSON序列化和反序列化的速度.为了防止由于内 ...

  4. gson 解析json_Gson示例教程解析JSON

    gson 解析json Welcome to Gson Example Tutorial. In last post we looked at the Java JSON API and you ca ...

  5. Android 使用Gson解析json用法

    目前解析json有三种工具:org.json(Java常用的解析),fastjson(阿里巴巴工程师开发的),Gson(Google官网出的),解析速度最快的是Gson,下载地址:https://co ...

  6. Android Gson解析json详解

    目前解析json有三种工具:org.json(Java常用的解析),fastjson(阿里巴巴工程师开发的),Gson(Google官网出的),解析速度最快的是Gson,下载地址:https://co ...

  7. Android 使用Gson解析json案例详解

    一.目前解析json有三种工具:org.json(Java常用的解析),fastjson(阿里巴巴工程师开发的),Gson(Google官网出的),解析速度最快的是Gson,下载地址:https:// ...

  8. Android Gson深入分析

    目前解析json有三种工具:org.json(Java常用的解析),fastjson(阿里巴巴工程师开发的),Gson(Google官网出的),解析速度最快的是Gson,下载地址:https://co ...

  9. GCC 连接器、链接标准库 gcc -l、链接手动创建库(指定目录的库 gcc -L)

    1. 链接器 链接器把多个二进制的目标文件(object file)链接成一个单独的可执行文件. 在链接过程中,它必须把符号(变量名.函数名等一些列标识符)用对应的数据的内存地址(变量地址.函数地址等 ...

最新文章

  1. sql server 2008建域时提示admin密码不符合要求解决方法
  2. mysql 写锁需要等待读锁释放吗_Mysql实战45讲笔记:5、全局锁和表锁
  3. 031 广播变量与累加器
  4. java关键字及其作用解释_java 常见关键字及其作用
  5. 大学期末考试SSH试题四
  6. android 基类fragment,Android DialogFragment 基类的定制
  7. P5708 【深基2.习2】三角形面积(python3实现)
  8. 信息学奥赛一本通C++语言——1010:计算分数的浮点数值
  9. github.com/oschwald/maxminddb-golang 安装报错
  10. java获取空闲端口_获取系统空闲端口
  11. NET中的三种Timer的区别和用法
  12. R语言——R和RStudio软件下载及安装
  13. Tabular Editor学习笔记_2
  14. win10 oracle安装
  15. 如何设置条形码的尺寸
  16. LOGO特训营 第四节 字体设计的重要性
  17. 上传文件submit提交form表单 success返回数据多了div获取不到正确的返回数据
  18. 需求分析(团队作业3)
  19. 开机广告页面2017流行样式 dialogTheme的popuwindow版本
  20. 物联网如何改变医疗保健行业

热门文章

  1. 你认为,世界上最无聊的工作是什么?
  2. java生成skp缩略图,目录下SketchUp文件联系表(自定义尺寸的缩略图集)怎样制作?...
  3. AMZI! PROLOG白皮书
  4. CCF 2018/09/02 买菜
  5. 测试开发-面试题目整理
  6. 用1000字来详细描述一下如何解决目前物联网与信息化方向的设备标准不统一的问题...
  7. D3地图上如何标注坐标点
  8. 造轮子了!NETCore跨平台UI框架,CPF
  9. FreeRTOS学习记录 02--任务篇
  10. 网状模型数据库和图数据库的区别