完全理解Gson(3):Gson反序列化
本文延续前一篇文章,继续介绍简单基本的Gson用法。这篇文章我们将介绍如何将复杂的JSON对象解析为Java对象,其中Java对象的结构可以与JSON对象不一致。我们还会看到如何使用Gson反序列化器(JsonDeserializer
Java文档)将JSON对象映射为Java对象。
观察
下面列出的所有代码都可以在 https://java-creed-examples.googlecode.com/svn/gson/Gson Deserialiser Example获取。绝大多数例子都不包含全部代码,与讨论主题不相关的代码片段有可能被忽略。读者可以从上面的链接下载或阅读全部代码。
对于不熟悉Gson的读者,鼓励您先阅读简单Gson用例 ,熟悉之后再开始阅读本篇内容。
一个简单的实例
比方说,我们有如下JSON对象,它包含两位著名作者的畅销Java书(Amazon)。
1
2
3
4
5
6
|
{ 'title' : 'Java Puzzlers: Traps, Pitfalls, and Corner Cases' , 'isbn-10' : '032133678X' , 'isbn-13' : '978-0321336781' , 'authors' : [ 'Joshua Bloch' , 'Neal Gafter' ] } |
上面的JSON对象包括4个字段,其中一个是数组。这些字段代表了我们的书籍。使用简单Gson实例中讨论的方法可能产生一个问题。默认情况下,Gson期望Java类中的变量名与JSON查找到的名称一样。因此,我们需要包含如下域名的类:title
、isbn-10
、isbn-13
和authors
。但是Java语言规范 (第六章)指出,Java变量名不能包含减号(-
)。
我们将在接下来的实例中看到如何使用JsonDeserializer
完全控制JSON的解析。另外我们也可以使用Gson注解实例中提到的注解。注解控制JSON解析的能力稍弱,但是使用简单便于理解。当然,注解也有它们的限制,不能解决这里提到的所有问题。
考虑下面简单的Java对象。
1
2
3
4
5
6
7
8
9
10
11
|
package com.javacreed.examples.gson.part1; public class Book { private String[] authors; private String isbn10; private String isbn13; private String title; // Methods removed for brevity } |
Java对象用来存储之前JSON对象中的书籍信息。注意,JSON对象有4个字段,每个变量对应一个JSON字段。这两个对象(Java和JSON)的结构不必一致。Java对象的结构可以与JSON对象不同。
为了将JSON对象解析成Java对象,我们需要创建自己的 JsonDeserializer
接口实例,并且注册到GsonBuilder
(Java文档)中。下面的例子展示了我们实现的 JsonDeserializer
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.javacreed.examples.gson.part1; import java.lang.reflect.Type; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; public class BookDeserializer implements JsonDeserializer<Book> { @Override public Book deserialize( final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException { //The deserialisation code is missing final Book book = new Book(); book.setTitle(title); book.setIsbn10(isbn10); book.setIsbn13(isbn13); book.setAuthors(authors); return book; } } |
上面的例子是不完整的,我们还需要增加最重要的部分——反序列化。在增加更多代码之前,我们先了解一下这个类变复杂之前的版本。
JsonDeserializer
接口需要一个类型,该类型是需要我们解析的对象类型。在这个例子里,我们将JSON对象解析成 Book
类型的Java对象。 deserialize()
方法的返回类型必须与泛型参数一致,为Book
类型。
Gson将JSON对象解析成一个JsonElement
(Java文档)类型的Java对象。一个 JsonElement
实例可以是下面类型之一:
JsonPrimitive
(Java Doc):例如一个字符串或整数。JsonObject
(Java文档):JsonElement
的集合,以名称(String
类型)为索引。 与Map<String, JsonElement>
(Java文档)相似。JsonArray
(Java文档):JsonElement
的集合。注意数组元素可以是任何4中类型,也支持混合类型。JsonNull
(Java文档):null
值。

上图显示了所有 JsonElement
的类型。 JsonObject
可以被认为是一个键值对的集合,其中值是JsonElement
类型。因此,该值可以是其他对象。

上图以 JsonObject
为根展示了一个JSON对象层级。特别需要注意,不同于Java,JSON支持不同类型的数组。上图中, JsonArray
包含JsonObject、JsonArray
和JsonPrimitive
。请注意,上图展示的JSON对象层级不反映前面列出的JSON对象。下面前面列出的JSON对象的JSON对象层级。

如果我们反序列化这个JSON对象,首先需要将给定的 JsonElement
转换为一个 JsonObject
。
1
2
|
// The variable 'json' is passed as a parameter to the deserialize() method final JsonObject jsonObject = json.getAsJsonObject(); |
使用相似的方法,JsonElement
可以转换成其他任何类型。
JsonObject
中的元素可以使用名称进行检索。例如,要从上面列出的JSON对象检索title
元素,我们可以进行下面操作。
1
2
3
|
// The variable 'json' is passed as a parameter to the deserialize() method final JsonObject jsonObject = json.getAsJsonObject(); JsonElement titleElement = jsonObject.get( "title" ) |
返回的对象不是一个 String
,而是另一个 JsonElement
。可以调用 getAsString()
方法将 JsonElement
转换为 String
,代码如下:
1
2
3
4
|
// The variable 'json' is passed as a parameter to the deserialize() method final JsonObject jsonObject = json.getAsJsonObject(); JsonElement titleElement = jsonObject.get( "title" ) final String title = jsonTitle.getAsString(); |
下面的例子展示了如何使用定制的反序列化器转换上面列出的JSON对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
package com.javacreed.examples.gson.part1; import java.lang.reflect.Type; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; public class BookDeserializer implements JsonDeserializer<Book> { @Override public 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; } } |
上例中,我们检索JSON元素和它的4个字段,并返回了一个 Book
实例。
在可以使用新的反序列化器之前,必须指定Gson使用我们的反序列化器来解析 Book
类型的对象,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.javacreed.examples.gson.part1; import java.io.InputStreamReader; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class Main { public static void main(String[] args) throws Exception { // Configure Gson GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Book. class , new BookDeserializer()); Gson gson = gsonBuilder.create(); // The JSON data try (Reader reader = new InputStreamReader(Main. class .getResourceAsStream( "/part1/sample.json" ), "UTF-8" )){ // Parse JSON to Java Book book = gson.fromJson(reader, Book. class ); System.out.println(book); } } } |
上例中,我们通过 GsonBuilder
创建了一个 Gson
实例。使用 registerTypeAdapter()
方法向Gson注册了我们的反序列化器,并指定反序列化 Book
类型对象时使用我们定义的反序列化器。当请求Gson反序列化一个 Book
类对象时,Gson将使用我们定义的反序列化器。下面的步骤描述了我们调用 gson.fromJson(data, Book.class)
时发生了什么。
- 将输入解析成
JsonElement
对象。注意,即使对象的类型是JsonElement
,输入可以是任何类型。在这个阶段,JSON对象字符串被反序列化为JsonElement
类型的Java对象。这个步骤还确保给定JSON数据的有效性。 - 检索给定对象的反解析器,本例中是
BookDeserializer
实例。 - 调用
deserialize()
方法并提供必需的参数。例子里,将调用我们的deserialize()
方法。这里,将从给定的JsonElement
对象创建一个Book
类型对象。这是Java内部的转化。 - 返回
deserialize()
方法的返回值到调用者fromJson()
方法。这一步像一个链条,Gson从我们的反序列化器接收一个对象并返回给它的调用者。
执行上面的例子可能得到下面的输出:
1
2
3
4
5
|
Java Puzzlers: Traps, Pitfalls, and Corner Cases [ISBN- 10 : 032133678X] [ISBN- 13 : 978 - 0321336781 ] Written by: >> Joshua Bloch >> Neal Gafter |
至此,我们结束了简单的例子。本例是后续更复杂例子的引子。在下一个例子里,我们将讨论当前对象的一个增强版本,该版本的作者对象不仅是一个简单的字符串,而是一个对象。
嵌套对象
本例中,我们将描述如何反序列化嵌套对象,也就是对象包含对象。这里,我们将介绍一个新的实体,作者。一本书,除了有标题和ISBN号,还可以有多个作者。换句话说,每个作者可以写多本书。为了增加新的实体,本例中的JSON对象做了修改,与前例不同:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
{ 'title' : 'Java Puzzlers: Traps, Pitfalls, and Corner Cases' , 'isbn' : '032133678X' , 'authors' :[ { 'id' : 1 , 'name' : 'Joshua Bloch' }, { 'id' : 2 , 'name' : 'Neal Gafter' } ] } |
稍微调整了JSON对象的结构并用JSON对象的作者数组代替了之前的原型,如下图:

我们还是以一本书为例,只是这次我们有了更复杂和更详细的JSON对象。除了 name字段
,作者对象还有一个 id字段
。为这个模型增加了新类称为 Author
, Book
类用它保存作者信息。这立即导致如下问题。
如何反序列化新的 Author
类?
这里有几种选择。
- 我们可以更新
BookDeserializer
并增加反解析作者信息的代码。这有个限制,它将Author
的反序列化与Book
绑定了,因此不推荐这个方法。 - 我们可以使用默认的Gson实现,该方法在这个例子中工作正常,因为Java对象(
Author
类)和JSON对象有同名的字段,可以进行简单Gson实例文中提到的反序列化。 - 或者,我们可以写一个
AuthorDeserializer
类,该类会处理Author的反序列化。
我们从第二种选择开始,保证改变最小化,例子尽量简单。然后,我们增加新的反序列化器来展示Gson的灵活性。
JsonDeserializer
提供了一个 JsonDeserializationContext
(Java文档)实例作为deserialize()
方法的第三个参数。我们还没有用过这个参数。我们可以将对象的反序列化委托给指定的 JsonDeserializationContext
实例。它将反序列化给定的 JsonElement
并返回一个指定类型的实例,代码如下。
1
|
Author author = context.deserialize(jsonElement, Author. class ); |
上例将 Author
类的反序列化委托给 context
变量。反过来,它试图搜索已注册的可以反序列化 Author
类的 JsonDeserialize
实例,如果未发现注册的实例,它将使用简单Gson实例中提到的默认机制。
我们的例子使用了一个 Author
数组,因此我们需要使用正确的类型,例子如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package com.javacreed.examples.gson.part2; import java.lang.reflect.Type; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; public class BookDeserializer implements JsonDeserializer<Book> { @Override public Book deserialize( final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException { final JsonObject jsonObject = json.getAsJsonObject(); final String title = jsonObject.get( "title" ).getAsString(); final String isbn10 = jsonObject.get( "isbn-10" ).getAsString(); final String isbn13 = jsonObject.get( "isbn-13" ).getAsString(); // Delegate the deserialization to the context Author[] authors = context.deserialize(jsonObject.get( "authors" ), Author[]. class ); final Book book = new Book(); book.setTitle(title); book.setIsbn10(isbn10); book.setIsbn13(isbn13); book.setAuthors(authors); return book; } } |
从 JsonPrimitive
转换成 JsonObject
是十分简单直接的,就像上面例子中看到的那样。
与BookDeserialiser类似
,我们可以编写 ArthurDeserialiser
类并使用处理书籍相似的方式反序列化作者。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.javacreed.examples.gson.part2; import java.lang.reflect.Type; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; public class AuthorDeserializer implements JsonDeserializer { @Override public Author deserialize( final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException { final JsonObject jsonObject = json.getAsJsonObject(); final Author author = new Author(); author.setId(jsonObject.get( "id" ).getAsInt()); author.setName(jsonObject.get( "name" ).getAsString()); return author; } } |
为了使用 ArthurDeserialiser
,我们需要向 GsonBuilder
注册,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.javacreed.examples.gson.part2; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import com.google.gson.Gson; import com.google.gson.GsonBuilder; public class Main { public static void main( final String[] args) throws IOException { // Configure GSON final GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Book. class , new BookDeserializer()); gsonBuilder.registerTypeAdapter(Author. class , new AuthorDeserializer()); final Gson gson = gsonBuilder.create(); // Read the JSON data try (Reader reader = new InputStreamReader(Main. class .getResourceAsStream( "/part2/sample.json" ), "UTF-8" )) { // Parse JSON to Java final Book book = gson.fromJson(reader, Book. class ); System.out.println(book); } } } |
没有必要改变 BookDeserialiser
类,因为作者的反序列化委托给了 context
变量。这是另一个使用 context
反序列化其他对象或嵌套对象的优点。运行上面的代码将产生下面的输出。
1
2
3
4
|
Java Puzzlers: Traps, Pitfalls, and Corner Cases [032133678X] Written by: >> [ 1 ] Joshua Bloch >> [ 2 ] Neal Gafter |
至此我们结束了嵌套对象的介绍。下一章节我们将看到如何引用JSON对象树中其他位置的JSON对象。
对象引用
考虑下面的JSON。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
{ 'authors' : [ { 'id' : 1 , 'name' : 'Joshua Bloch' }, { 'id' : 2 , 'name' : 'Neal Gafter' } ], 'books' : [ { 'title' : 'Java Puzzlers: Traps, Pitfalls, and Corner Cases' , 'isbn' : '032133678X' , 'authors' :[ 1 , 2 ] }, { 'title' : '<span class="wp_keywordlink"><a href="http://www.amazon.com/gp/product/B000WJOUPA/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=B000WJOUPA&linkCode=as2&tag=job0ae-20" title="Effective Java" rel="nofollow" target="_blank" class="external">Effective Java</a></span> (2nd Edition)' , 'isbn' : '0321356683' , 'authors' :[ 1 ] } ] } |
上面的JSON对象由两个作者和两本书组成。书有一个id到作者的引用,本例中书的 authors
字段只包含作者的id。这是一个很常见的场景,通过这个方法将减少JSON对象的大小,因为重复对象通过他们的id进行引用。下图展示了JSON新对象的层级。

这类似于关系型数据库(维基),其中book对象有一个到作者表的外键(维基)。新的JSON对象引入了需要解决的新挑战。当反序列化书籍对象时,我们需要保持作者对象,并从JSON对象层级的其他分支反序列化它们。书籍对象只有作者对象的id。作者对象的其他信息不在当前上下文中,需要从其他地方进行解析。
这里有多种方式来解决这个问题,下面列出了一些。
1. 一种方法是分两个阶段处理。首先将JSON对象解析成Java对象,这一步反序列化JSON中的书和作者对象。书籍类包含作者的id数组而不是作者的数组。接着,第二阶段,我们关联对象,将作者对象关联到书籍对象。下图显示了反解析流程。
两阶段处理过程
这个方法需要很多类,但是提供了很大的灵活性并且更好地分离了关注点。我们需要创建一组代表JSON对象的简单Java类,接着创建另一组满足我们需求(模型)的类。这个例子里,我们有一个 Book
和一个Author
类,总共两个。使用这个方法,我们最终将有4个类,两个代表书籍类,另两个代表作者类。本例使用这个方法似乎是可行的,但是当有数十个类时,就会变得十分复杂。
2. 另一种方法是提供包含所有作者的BookDeserialiser
类,接着使用反序列化器从公用对象检索所有作者。这种方法消除了中间状态,因为JSON对象没有经过中间阶段就被反序列化成适当的Java对象。
反序列化器共享对象
尽管这个方法听上去有吸引力,但它要求 BookDeserialiser
和 AuthorDeserialiser
共享一个对象。此外,当当检索作者时, BookDeserialiser
不得不引用这个共享对象来代替之前使用的JsonDeserializationContext
类。这个方法需要修改几个地方,反序列化器和main()
函数都需要修改。
3. AuthorDeserialiser
可以换成反序列化的作者,并在下次指定ID的请求时返回它们。这个方法十分有吸引力,因为它充分利用了 JsonDeserializationContext
,并且使得关系透明。不幸的是,它增加了复杂性,AuthorDeserialiser
需要处理缓存。按照这个说法,这种方法需要最少的修改,只有 AuthorDeserialiser
需要修改。
AuthorDeserialiser
反序列化器使用缓存对象
如上如所示,只有 AuthorDeserialiser
类访问缓存对象。系统里的其他部分不知道这一点。
所有方法都是可行的,而且每种都有他们的优缺点。我们将使用第三种方法,因为它对工程的影响最小。
观察
Data
类中处理关联逻辑。但与第三种方法相比,这需要很多修改。这就是使用第三种方法的原因。始终考虑改变,并尽量减少所需的工作。上面所示的JSON对象包含两个数组。我们需要新的Java类来反射这个JSON对象。
1
2
3
4
5
6
7
8
9
|
package com.javacreed.examples.gson.part3; public class Data { private Author[] authors; private Book[] books; // Methods removed for brevity } |
字段顺序决定了两个集合反序列化的顺序。在我们的例子中没有问题,在后面我们可以看到,书籍集合可以在作者集合之前被反序列化。
AuthorDeserialiser
类需要做出修改,它会缓存反序列化出的作者对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package com.javacreed.examples.gson.part3; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonPrimitive; public class AuthorDeserializer implements JsonDeserializer<Author> { private final ThreadLocal<Map<Integer, Author>> cache = new ThreadLocal<Map<Integer, Author>>() { @Override protected Map<Integer, Author> initialValue() { return new HashMap<>(); } }; @Override public Author deserialize( final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException { // Only the ID is available if (json.isJsonPrimitive()) { final JsonPrimitive primitive = json.getAsJsonPrimitive(); return getOrCreate(primitive.getAsInt()); } // The whole object is available if (json.isJsonObject()) { final JsonObject jsonObject = json.getAsJsonObject(); final Author author = getOrCreate(jsonObject.get( "id" ).getAsInt()); author.setName(jsonObject.get( "name" ).getAsString()); return author; } throw new JsonParseException( "Unexpected JSON type: " + json.getClass().getSimpleName()); } private Author getOrCreate( final int id) { Author author = cache.get().get(id); if (author == null ) { author = new Author(); author.setId(id); cache.get().put(id, author); } return author; } } |
我们在这个类中做了一些修改。让我们一个个地说明。
1.作者保存在下面的对象中
1
2
3
4
5
6
|
private final ThreadLocal<Map<Integer, Author>> cache = new ThreadLocal<Map<Integer, Author>>() { @Override protected Map<Integer, Author> initialValue() { return new HashMap<>(); } }; |
它使用 Map<String, Object>
提供缓存机制。map变量保存在ThreadLocal
(Java文档)中,以隔离多线程之间的状态。这个类允许多线程使用相同的变量而不会影响到其他线程。
观察
2.总是通过下面方法得到作者。
- 12345678
private
Author getOrCreate(
final
int
id) {
Author author = cache.get().get(id);
if
(author ==
null
) {
author =
new
Author();
cache.get().put(id, author);
}
return
author;
}
这个方法首先从缓存中获取作者实例,如果没有找到给定id的作者,那么将创建一个并加入到缓存中。
这个方法允许我们只用id就能创建作者,之后当它们可用时公布它们的内容。这就是为什么反序列化属性不影响输出。我们可以先反序列化书籍类,再反序列化作者类。在这个例子中,首先使用id创建作者,然后给他们增加名字。
3.对 deserialize()
函数进行修改来处理新的需求。因为修改了很多地方,我们将拆分这个方法,并逐个讲解。反序列化器可以接收JsonPrimitive
变量或者JsonObject
变量。 当BookDeserialiser
执行下面的代码时,传递给 AuthorDeserialiser
的 JsonElement
变量将会是一个JsonPrimitive
实例。
1
|
// This is executed within the BookDeserialiser Author[] authors = context.deserialize(jsonObject.get("authors"), Author[].class); |
下图显示了这个过程。

上下文收到 BookDeserialiser
委托反序列化 Author
数组的操作,并返回一个整型数组。对于每个整数,上下文作为一个 JsonPrimitive
对象传递给 AuthorDeserialiser
的 deserialize()
方法。
另一方面,当作者被反序列化后,我们将收到一个包含作者和他或她详细信息的 JsonObject
实例。因此,在我们转换给定的JsonElement
对象前,需要校验他是否是正确的类型。
1
2
3
4
5
6
|
// Only the ID is available if (json.isJsonPrimitive()) { final JsonPrimitive primitive = json.getAsJsonPrimitive(); final Author author = getOrCreate(primitive.getAsInt()); return author; } |
上例所示,只有id是有效的。 JsonElement
转换为JsonPrimitive
接着又转换为 int
.。
JsonElement
可以是JsonObject
类型,如下所示。
1
2
3
4
5
6
7
8
|
// The whole object is available if (json.isJsonObject()) { final JsonObject jsonObject = json.getAsJsonObject(); final Author author = getOrCreate(jsonObject.get( "id" ).getAsInt()); author.setName(jsonObject.get( "name" ).getAsString()); return author; } |
这个例子中,在返回author前,向 getOrCreate()
方法返回的 Author
实例中增加name字段。
最后,如果给定的JsonElement
实例既不是 JsonPrimitive
也不是 JsonObject
,将抛出一个异常说明不支持指定类型。
1
|
throw new JsonParseException( "Unexpected JSON type: " + json.getClass().getSimpleName()); |
以上代码块列出了所有需要的修改,以适应和应对新的挑战。BookDeserialiser
类和 main()
方法不需要任何修改。执行main()
将得到如下输出。
1
|
Output missing... |
这个例子总结了我们关于Gson反序列化器的文章。使用定制反序列化器不困难,可以使我们毫不费力的处理不同的JSON示例。需要注意的是,在Java业务对象不需要与解析的JSON对象对应。此外,我们可以使用新的JSON表示现有的Java对象。有些问题可能比其他问题解决起来更具挑战性。试着最大程度减少对现有代码的修改,你的设计将更具灵活性(尽可能不要修改)。
原文链接: javacreed 翻译: ImportNew.com- liken
译文链接: http://www.importnew.com/16786.html
完全理解Gson(3):Gson反序列化的更多相关文章
- 你真的会用Gson吗?Gson使用指南(4)
原文出处: 怪盗kidou 注:此系列基于Gson 2.4. 本次文章的主要内容: TypeAdapter JsonSerializer与JsonDeserializer TypeAdapterFac ...
- 你真的会用Gson吗?Gson使用指南(3)
原文出处: 怪盗kidou 注:此系列基于Gson 2.4. 本次的主要内容: 字段过滤的几种方法 基于@Expose注解 基于版本 基于访问修饰符 基于策略(作者最常用) POJO与JSON的字段映 ...
- 你真的会用Gson吗?Gson使用指南(2)
注:此系列基于Gson 2.4. 上一篇文章 你真的会用Gson吗?Gson使用指南(1) 我们了解了Gson的基础用法,这次我们继续深入了解Gson的使用方法. 本次的主要内容: Gson的流式反序 ...
- 你真的会用Gson吗?Gson使用指南(1)
JSON (官网) 是一种文本形式的数据交换格式,它比XML更轻量.比二进制容易阅读和编写,调式也更加方便.其重要性不言而喻.解析和生成的方式很多,Java中最常用的类库有:JSON-Java.Gso ...
- 你真的会用Gson吗?Gson使用指南
你真的会用Gson吗?Gson使用指南(一) 你真的会用Gson吗?Gson使用指南(二) 你真的会用Gson吗?Gson使用指南(三) 你真的会用Gson吗?Gson使用指南(四)
- 【转】通俗理解Java序列化与反序列化
一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存 ...
- java基础知识-序列化/反序列化-gson基础知识
以下内容来之官网翻译,地址 1.Gson依赖 1.1.Gradle/Android dependencies { implementation 'com.google.code.gson:gson:2 ...
- Gson含抽象类的反序列化
Gson含抽象类的反序列化 场景描述: 反序列化A类的时候,这个类里面有一个抽象类属性B,B的实现类C里面又有一个抽象类属性D,D的实现类是E 实体类准备 public class A impleme ...
- Gson、jackson 序列化,反序列化(单个、集合)
实体类: package com.nf.redisDemo1.entity; public class News { private long id; private String title; pr ...
- Gson反序列化泛型实例
1 package com.ppmoney.g2.mapper; import com.google.common.reflect.TypeToken; import com.google.gson. ...
随机推荐
- web自动化测试:watir+minitest(四)
脚本连跑: rake是ruby中的一个构建工具,和make很像.允许用ruby来写rakefile. 我们使用rake以任务的方式来运行我们的脚本集. 新建Rakefile文件,写入如下内容: req ...
- P3141 [USACO16FEB]围栏Fenced In_Platinum
题目描述 Farmer John has realized that many of his cows are strangely agoraphobic (being fearful of larg ...
- 在浏览器中进行深度学习:TensorFlow.js (八)生成对抗网络 (GAN
Generative Adversarial Network 是深度学习中非常有趣的一种方法.GAN最早源自Ian Goodfellow的这篇论文.LeCun对GAN给出了极高的评价: “There ...
- ROS内usb_cam包使用注意事项
1.查看摄像头支持的pixel-format: 方法: v4l2-ctl --list-formats-ext -d /dev/video0
- Codeforces Round #357 (Div. 2) C
C. Heap Operations time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- Visual Studio中的/MD, /MT, /MDd, /MTd 选项
Visual Studio中/MD, /MT, /MDd, /MTd表示多线程模块是否为dll.对于这几个选项我的理解如下: /MD: 定义了_MT和_DLL,让程序用多线程和dll版本的运行库. / ...
- elemetUi 组件--el-checkbox
[需求]实现选择右边的
- Binary Indexted Tree 树状数组入门
感谢http://www.cnblogs.com/xudong-bupt/p/3484080.html 树状数组(BIT)是能够完成下述操作的数据结构: 给定一初始值全为零的数列a1,a2a,a3.. ...
- 汕头市队赛 SRM 08 C
C-3 SRM 08 描述 给一个图,n 个点 m 条双向边,每条边有其长度.n 个点中有 k 个是特殊点,问任意两个特殊点的最短路是多少. 输入格式 第一行三个整数 n m k 第二行 k 个整数 ...
- Custom Email Attribute在客户端不起作用原因
原文发布时间为:2011-07-16 -- 来源于本人的百度文章 [由搬家工具导入] Custom Email Attribute在客户端不起作用原因,就是未实现 IClientValidatable ...