Gson 使用指南(中文)

来源:互联网 发布:淘宝直播时怎么调镜像 编辑:程序博客网 时间:2024/06/03 10:13

整体概括

引用:http://blog.csdn.net/afeiluo/article/details/50484949/

Gson 是一个将Java对象转换成Json字符串,将Json字符串转换陈成Java对象的工具库

Gson能够处理任何类型的Java对象,甚至包括那些你没有源代码的Java类(不了解对象的属性)

Gson能干什么

  • 提供简单的方法(工厂方法)将java对象转换成json字符串,反之亦然。
  • 已经存在的不可修改的不具名的对象转换成json字符串或者从json字符串转换而来
  • 可以定制对象转换成json字符串的形式
  • 支持任意类型的复杂的对象
  • 生产简洁可靠的json字符串输出

Gson的性能和可扩展性

下面是一些在windows平台上使用测试类来测试性能的度量方法以及结果

  • 字符串:反序列化超过25MB大小的字符串没有任何问题(看 PerformanceTest类中的disabled_testStringDeserializationPerformance方法)
  • 大集合处理: 
    • 序列化了一个超过140万个对象的集合(看 PerformanceTest类中的disabled_testLargeCollectionSerialization方法)
    • 反序列化一个超哥87000个对象的集合(看 PerformanceTest类中的disabled_testLargeCollectionDeserialization方法)
  • Gson1.4版本将反序列化字符数组和集合的大小限制从80KB提升到了11MB

使用Gson的用户

Gson最初是为Google的内部项目而开发的,现在它已经在世界上的多个项目和公司中得到了运用,详细见这里

通过Maven来使用Gson

在Maven2/3中使用下面的依赖来使用Gson

<code class="language-xml hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dependencies</span>></span>    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!--  Gson: Java to Json conversion --></span>    <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dependency</span>></span>      <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">groupId</span>></span>com.google.code.gson<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">groupId</span>></span>      <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">artifactId</span>></span>gson<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">artifactId</span>></span>      <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">version</span>></span>2.5<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">version</span>></span>      <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">scope</span>></span>compile<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">scope</span>></span>    <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dependency</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">dependencies</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

这样你的项目中就能使用Gson了

原生类型例子

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Serialization</span>Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Gson();gson.toJson(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ==> 1</span>gson.toJson(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"abcd"</span>);       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ==> "abcd"</span>gson.toJson(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Long(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>)); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ==> 10</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] values = { <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> };gson.toJson(values);       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ==> [1]   </span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Deserialization</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> one = gson.fromJson(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"1"</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>.class);Integer one = gson.fromJson(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"1"</span>, Integer.class);Long one = gson.fromJson(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"1"</span>, Long.class);Boolean <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span> = gson.fromJson(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"false"</span>, Boolean.class);String str = gson.fromJson(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"\"abc\""</span>, String.class);String anotherStr = gson.fromJson(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"[\"abc\"]"</span>, String.class);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

对象例子

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">class BagOfPrimitives {  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> value1 = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String value2 = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"abc"</span>;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">transient</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> value3 = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;  BagOfPrimitives() {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// no-args constructor</span>  }}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Serialization</span>BagOfPrimitives obj = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> BagOfPrimitives();Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Gson();String json = gson.toJson(obj);  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ==> json is {"value1":1,"value2":"abc"}</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

注意不要序列化一个含有循环应用的对象(会导致无限递归)

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Deserialization</span>BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ==> obj2 is just like obj</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

更好的序列化对象

  • 对象的成员建议使用private
  • 没有必要使用注解来标示要序列化和反序列化的域,默认情况下当前的类及其父类所有的域都会被处理
  • 如果某一个域(成员变量)被标示为transient类型,默认情况下是不会对他进行序列化反序列化(例外)
  • Gson能够正确处理null
  • 序列化时,null值默认情况下是忽略处理的
  • 反序列化是,json字符串中缺少的字段映射到对象中响应的属性为null
  • synthetic关键字标记的域不会被序列化和反序列化,什么是synthetic见这里
  • 内部类中应用外部类、匿名类、本地类(什么是本地类)作为域的时候不会被序列化和反序列化

嵌套类(包括内部类)的序列化

Gson可以相当容易的序列化静态嵌套类

Gson同样也可以发序列化静态嵌套类,然而Gson**不能够**直接反序列化纯内部类,这是因为在反序列的时候内部类的构造函数获取不到一个外部类的引用,你可以通过将内部类声明为静态内部类或者提供一个定制的InstanceCreator来解决这个问题,下面是例子:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">A</span> {</span>   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String a;  class B {     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String b;     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">B</span>() {      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// No args constructor for B</span>    }  } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

注意:上面的class B默认情况下不能够被Gson序列化 
Gson不能够将{"b":"abc"}反序列化到B的实例中,如果B是静态内部类的话则可以反序列化,另外还可以通过为B重写一个instance creator来实现反序列化。

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">InstanceCreatorForB</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">InstanceCreator</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">A</span>.<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">B</span>> {</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> A a;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">InstanceCreatorForB</span>(A a)  {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.a = a;  }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> A.B <span class="hljs-title" style="box-sizing: border-box;">createInstance</span>(Type type) {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> a.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> B();  }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

上面的方法(重新instance creator)可以反序列化B,但是不推荐这种方法。

序列化数组

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Gson();<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] ints = {<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>};String[] strings = {<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"abc"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"def"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ghi"</span>};<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Serialization</span>gson.toJson(ints);     <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ==> [1,2,3,4,5]</span>gson.toJson(strings);  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ==> ["abc", "def", "ghi"]</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Deserialization</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[] ints2 = gson.fromJson(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"[1,2,3,4,5]"</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>[].class); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// ==> ints2 will be same as ints</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

同样支持多维任意复杂的数组。

序列化集合

Gson gson = new Gson();Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);// SerializationString json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]// DeserializationType collectionType = new TypeToken<Collection<Integer>>(){}.getType();Collection<Integer> ints2 = gson.fromJson(json, collectionType);// ==> ints2 is same as ints

定义集合的方式很丑陋,但是在java中没法避免

序列化集合的限制

  • 可以序列化任何对象的集合但是不能够反序列化
  • 因为没有任何办法让用户知道反序列化结果对象的类型
  • 反序列化时,集合必须是一个特定的泛型

以上这些情况都需要注意,但是当有一个很好的编程习惯的时候很少会犯上面的错误

序列化反序列化泛型

当调用toJson(obj)去序列化对象的时候Gson内部会调用obj.getClass()去获取obj的类型信息,类似的,你在调用fromJson(json,MyClass.class)方法反序列化时需要显示的传递要序列化的对象的类型信息Myclass.class,这种方式当序列化和反序列化的对象时非泛型的时候回工作得很好,但是,如果目标对象时泛型的时候,泛型的信息会由于java的擦除机而丢失,下面的例子说明了这种情况:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">class Foo<T> {  T value;}Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Gson();Foo<Bar> foo = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Foo<Bar>();gson.toJson(foo); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// May not serialize foo.value correctly</span>gson.fromJson(json, foo.getClass()); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Fails to deserialize foo.value as Bar</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

上面的代码反序列化时不能够将json解释成Bar类型,这是由于调用foo.getCalss()得到的是一个原生类型Foo.class。这样的话Gson就不知道反序列化目标的类型应该是Foo。

你可以通过为泛型定义明确的参数类型来解决这个问题,你像下面这样使用TypeToken 类:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Type fooType = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> TypeToken<Foo<Bar>>() {}.getType();gson.toJson(foo, fooType);gson.fromJson(json, fooType);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

获取fooType的秘密就是通过定义一个包含getType()方法的匿名本地内部类来获取一个具体的参数化类型

序列化和反序列化任意对象类型的集合

有时候你需要处理包含混合类型的JSON数组,像这种 ['hello',5,{name:'GREETINGS',source:'guest'}]

等价的集合是:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Collection collection = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList();collection.add(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"hello"</span>);collection.add(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);collection.add(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Event(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"GREETINGS"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"guest"</span>));</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

Event类的定义如下:

class Event {private String name;private String source;private Event(String name, String source) {this.name = name;this.source = source;   }}

当然你使用toJson(collection)来序列化的时候不会出现任何问题

但是,使用fromJson(json,Collection.class)来反序列化的时候却会失败,这是因为Gson不知道如何映射具体的类型。Gson需要提提供一般类型的集合来充当第二参数,为了处理这种情况的反序列化,你可以使用下面这三种方法:

  1. 使用Gson的解析器API去解析每一个数组元素然后使用Gson.fromJson()方法来反序列化每一个元素,这种方法这种推荐,这里一个例子解释了使用方法
  2. 为Collection.class定义一个类型适配器负责将每一个数组元素映射到适当的类型,当时这种方法的一个缺点是它会让Gson反序列化其他集合类型时不够通用
  3. MyCollectionMemberType注册一个类型适配器在fromJson方法中使用Collection<MyCollectionMemberType>

内置序列化器和反序列化器

针对经常使用的类Gons以一些内置的序列化器和反序列化器,但是他们的默认输出的形式有可能不正确,下面是一些具体的类:

  1. java.net.URL 对应像"https://github.com/google/gson/"的字符串
  2. java.net.URL 对应像"/google/gson/" 的字符串

你可以在这里找到像JodaTime这样的常用类

定制序列化和反序列化过程

有时候默认的输出结果并不是你希望的,尤其是处理库函数烈性的时候(DateTime,etc).Gson允许你定制序列化和反序列化过程,一般是通过下面的两步来完成:

  • Json Serialiers: 需要为对象定义个特定的序列化器
  • Json Deserialiers: 需要为某一个类型定义一个特定的反序列化器
  • Instance Creators: 当无参构造函数可用或者注册了一个反序列化器时不需要
<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">GsonBuilder gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> GsonBuilder();gson.registerTypeAdapter(MyType2.class, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> MyTypeAdapter());gson.registerTypeAdapter(MyType.class, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> MySerializer());gson.registerTypeAdapter(MyType.class, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> MyDeserializer());gson.registerTypeAdapter(MyType.class, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> MyInstanceCreator());</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

registerTypeAdapter 调用会检查typeAdapter(第二个参数)是否实现了上面三个接口中的一个或者多个,同时注册这个typeAdapter。

自己定义个序列化器

下面是一个例子来说明如何写一个序列化DateTime类的序列化器:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">DateTimeSerializer</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">JsonSerializer</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">DateTime</span>> {</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> JsonElement <span class="hljs-title" style="box-sizing: border-box;">serialize</span>(DateTime src, Type typeOfSrc, JsonSerializationContext context) {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> JsonPrimitive(src.toString());  }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

Gson会在序列化DateTime类型的时候调用serialize()方法

自己定义一个反序列化器

下面的例子说明了如何自己写一个反序列化DateTime类型的反序列化器

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">DateTimeDeserializer</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">JsonDeserializer</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">DateTime</span>> {</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> DateTime <span class="hljs-title" style="box-sizing: border-box;">deserialize</span>(JsonElement json, Type typeOfT, JsonDeserializationContext context)      <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> JsonParseException {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DateTime(json.getAsJsonPrimitive().getAsString());  }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

Gson会在将一个JSON字符串片段反序列化成一个DateTime类型对象的时候调用

更好的使用序列化器和反序列化器

通常你需要为所有的泛型注册一个单个的处理器相比于原生类型

  • 例如,你需要一个Id类型来表示id(啥玩意儿…就是标示的意思咯)
  • Id<T> 类型对所有的泛型有一样的序列化过程 
    • 输出id的值
  • 反序列化类似但是有不一样的地方 
    • 需要调用 new Id(Class<T>,String)获取一个Id的实例

Gson支持注册单个处理器(Json Serialiers,Json Deserialiers,Instance Creators这三个中的一个),你也可以为特定的泛型注册一个特定的处理器(像Id<RequiresSpecialHandling>需要特殊处理),toJson()fromJson()方法中的Type参数包含了你为所有的泛型写入单个处理器的泛型信息。

写一个Instance Creator

当反序列化一个对象的时候,Gson创建一个这个类的默认实例,一个序列化反序列化的类中应该有一个无参的构造函数。

  • 不用关心构造函数是public或者private

典型的,Instance Creators 用在处理库中那些没有默认无参构造函数的类

Instance Creator 例子

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MoneyInstanceCreator</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">InstanceCreator</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Money</span>> {</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Money <span class="hljs-title" style="box-sizing: border-box;">createInstance</span>(Type type) {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Money(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"1000000"</span>, CurrencyCode.USD);  }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

参数Type可以相应的是泛型

  • 触发需要特定泛型类型的构造函数
  • 例如,Id类保存了id的信息

InstanceCreator 作为一个参数化类型

有时候你需要实例化的类型是参数化类型,一般,这并没有问题因为实际的实例是原生类型,下面是一个例子:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">class MyList<T> extends ArrayList<T> {}class MyListInstanceCreator implements InstanceCreator<MyList<?>> {    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@SuppressWarnings</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"unchecked"</span>)  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> MyList<?> <span class="hljs-title" style="box-sizing: border-box;">createInstance</span>(Type type) {    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// No need to use a parameterized list since the actual instance will have the raw type anyway.</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> MyList();  }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

然后,有时候你需要创建一个基于实际的参数类型的实例,这种情况下,你可以使用传递给createInstance方法的类型参数,下面是个例子:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Id</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">T</span>> {</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Class<T> classOfId;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> value;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Id</span>(Class<T> classOfId, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> value) {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.classOfId = classOfId;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.value = value;  }}class IdInstanceCreator implements InstanceCreator<Id<?>> {  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Id<?> <span class="hljs-title" style="box-sizing: border-box;">createInstance</span>(Type type) {    Type[] typeParameters = ((ParameterizedType)type).getActualTypeArguments();    Type idType = typeParameters[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Id has only one parameterized type T</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> Id.get((Class)idType, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>L);  }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>

在上面的例子中,如果不传递实际的参数类型Id的实例不可能创建,我们解决这个方法是通过使用createInstance的参数类型Type,这的type是参数化类型Id,所以最终InstanceCreator返回的实例应该是Id,由于Id只含有一个参数化类型,T,所以使用反射的api函数获取到这个class并返回。

紧凑和漂亮的输出格式

默认的GSON输出是一种紧凑的json格式,这意味着在json的输出中不会有空格,因此,同样在名和值之间,对象的属性之间,对象数组之间都也不会有空格,同样,”null”值也会在结果中被忽略(注意:空值仍然在集合和数组中)。

如果你想使用漂亮的输出格式,你必须使用GsonBuilder来配置Gson对象,由于公共API中没有暴露JsonFormatter,所以客户端不能编辑默认的json输出格式,现在我们提供的默认的JsonPrintFormatter 它每行有80个字符,2个字符缩进,4个字符右边距

下面的例子展示了使用默认的JsonPrintFormatter来配置Gson实例(替代JsonCompactFormatter)

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> GsonBuilder().setPrettyPrinting().create();String jsonOutput = gson.toJson(someObject);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

支持空值

默认的实现Gson会忽略掉为null的域,这样就能提供一种比较紧凑的输出格式,但是当json格式的字符串反序列化成java对象的时候需要为那些为空的域提供一个默认值

下面是你怎么配置一个Gson对象来输出null:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> GsonBuilder().serializeNulls().create();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

注意:当使用Gson序列null时,它添加了一个JsonNull元素到JsonElement结构中,因此对象可以被用到定制的序列化/反序列化过程中 
下面是一个例子:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Foo</span> {</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String s;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Foo</span>() {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);  }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Foo</span>(String s, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i) {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.s = s;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.i = i;  }}Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> GsonBuilder().serializeNulls().create();Foo foo = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Foo();String json = gson.toJson(foo);System.out.println(json);json = gson.toJson(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);System.out.println(json);The output is:{<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"s"</span>:<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"i"</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li></ul>

版本支持

使用@since直接能够获取对象的多个版本的数据,这个注解能够用在类,域,未来甚至可以在方法上,为了利用这个特点,你必须配置Gson实例,让它忽略高过某个版本的域/对象。如果没有配置Gson中的版本那么默认情况下所有的域忽视注解都会被序列化。

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">VersionedClass</span> {</span>  <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Since</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.1</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String newerField;  <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Since</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span>) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String newField;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String field;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">VersionedClass</span>() {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.newerField = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"newer"</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.newField = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"new"</span>;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.field = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"old"</span>;  }}VersionedClass versionedObject = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> VersionedClass();Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> GsonBuilder().setVersion(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span>).create();String jsonOutput = gson.toJson(someObject);System.out.println(jsonOutput);System.out.println();gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Gson();jsonOutput = gson.toJson(someObject);System.out.println(jsonOutput);The output is:{<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"newField"</span>:<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"new"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"field"</span>:<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"old"</span>}{<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"newerField"</span>:<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"newer"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"newField"</span>:<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"new"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"field"</span>:<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"old"</span>}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul>

从序列化反序列化中排除某些域

Gson支持一些排除顶级类,成员序列化和反序列化的方法,下面的方法可以排除与和类的序列化,如果下面的方法还不满足你的需求,你还可以使用这里的方法

Java标识符排除法

默认情况下,你可以标示一个域为transient,这样它就不会被序列化。同样一个域被标示为static同样也会被排除,如果你想包含某些transient 域你可以按照下面的方法做:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.lang.reflect.Modifier;Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> GsonBuilder()    .excludeFieldsWithModifiers(Modifier.STATIC)    .create();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

注意:你可以excludeFieldsWithModifiers方法中使用多个标识符常量,例如:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> GsonBuilder()    .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)    .create();</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

Gson的@Expose注解

你可以使用这个注解来表示特定的域从而来排除被序列化、反序列化为JSON,你可以通过使用new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() 来创建Gson对象,创建的这个Gson实例将排除所有没有用@Expose注解标示的域。

使用用户自定义的排除策略

如果上面的排除方法都不能满足你的需求,你可以定制自己的排除策略,然后配置到Gson实例中去,一般是通过继承ExclusionStrategy类来实现的

下面的例子展示了如果排除具有指定注解的域

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Retention</span>(RetentionPolicy.RUNTIME)<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Target</span>({ElementType.FIELD})<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> @<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Foo</span> {</span>  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Field tag only annotation</span>}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">SampleObjectForTest</span> {</span>  <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Foo</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> annotatedField;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String stringField;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> longField;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Class<?> clazzField;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">SampleObjectForTest</span>() {    annotatedField = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>;    stringField = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"someDefaultValue"</span>;    longField = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1234</span>;  }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MyExclusionStrategy</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ExclusionStrategy</span> {</span>  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> Class<?> typeToSkip;  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-title" style="box-sizing: border-box;">MyExclusionStrategy</span>(Class<?> typeToSkip) {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.typeToSkip = typeToSkip;  }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">shouldSkipClass</span>(Class<?> clazz) {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (clazz == typeToSkip);  }  <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">shouldSkipField</span>(FieldAttributes f) {    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> f.getAnnotation(Foo.class) != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;  }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) {  Gson gson = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> GsonBuilder()      .setExclusionStrategies(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> MyExclusionStrategy(String.class))      .serializeNulls()      .create();  SampleObjectForTest src = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SampleObjectForTest();  String json = gson.toJson(src);  System.out.println(json);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li></ul>

输出:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">{<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"longField"</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1234</span>}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

重命名JSON域支持

Gson也支持一些预先的域命名策略,通过这侧策略来讲标准的java域名称转换成Json的域名称,这个类FieldNamingPolicy提供了一些域处理命名规则的策略

同时Gson也提供了一些基于注解定制域名称的策略。但是要注意,基于注解的基本命名策略会验证域名称的合法性从而会导致一些“运行时”异常,下面的例子展示了如何利用基本的Gson命名来策略:

private class SomeObject {@SerializedName("custom_naming") private final String someField;private final String someOtherField;public SomeObject(String a, String b) {this.someField = a;this.someOtherField = b;}}SomeObject someObject = new SomeObject("first", "second");Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();String jsonRepresentation = gson.toJson(someObject);System.out.println(jsonRepresentation);

输出是:

{"custom_naming":"first","SomeOtherField":"second"}

在定制的序列化器和反序列化器之间分享状态

有时候你需要在定制的序列化器和反序列化器之间分享状态(讨论) 。你可以用下面的策略实现

  1. 在静态域中存储状态
  2. 声明序列化器和反序列化器为夫类型的内部类,使用父类型的实例域来存储状态
  3. 使用java的 ThreadLocal

1和2 线程不安全,3是线程安全的。

流式处理

此外根据Gson的对象模型和数据绑定功能,你可以使用Gson去读写流 
你可以从流式读写和对象模型中获取到最好的编程方法

设计中的问题

See the Gson design document for a discussion of issues we faced while designing Gson. It also include a comparison of Gson with other Java libraries that can be used for Json conversion.

未来的功能

For the latest list of proposed enhancements or if you’d like to suggest new ones, see the Issues sectionunder the project website.

0 0
原创粉丝点击