澳门新葡萄京娱乐场 4

澳门新葡萄京娱乐场Gson基本操作,JsonObject,JsonArray,String,JavaBean,List互转

Java Json
API:Gson使用简单入门

gson
github地址google/gson

本篇文章是基于Gson官方使用指导(Gson User
Guide)以及Gson解析的优秀外文(来自http://www.javacreed.com/
)做出的一个翻译和归纳。
博客原链接:
Gson全解析(上)-Gson基础
Gson全解析(中)-TypeAdapter的使用
Gson全解析(下)-Gson性能分析

通过调用 Gson API 可以把 Java 对象转换为 JSON
格式的字符串(项目主页)。在这篇文章中,我们将会讲到如何通过
Gson 默认实现和自定义实现方式,将 Java  对象转换为 JSON 字符串。


对于那些不熟悉 Gson 的读者,建议在读本篇文章之前读一下这两篇文章:简单
Gson 实例和 Gson
反序列化实例。另外,这篇文章的讲述方式和Gson反序列化实例一样,并且使用了相同的例子。

前言

最近在研究Retrofit中使用的Gson的时候,发现对Gson的一些深层次的概念和使用比较模糊,所以这里做一个知识点的归纳整理。

Gson(又称Google
Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。而JSON(JavaScript
Object Notation)
是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,广泛应用于各种数据的交互中,尤其是服务器与客户端的交互。


String、JsonObject、JavaBean 互相转换
    User user = new Gson().fromJson(jsonObject, User.class);
    User user = new Gson().fromJson(string, User.class);
    String string = new Gson().toJson(user);
    JsonObject jsonObject = new Gson().toJsonTree(user).getAsJsonObject(); 
    JsonObject jsonObject = new JsonParser().parse(string).getAsJsonObject();
String、JsonArray、List互相转换
    List<User> userList = gson.fromJson(string, new TypeToken<List<User>>() {}.getType()); 
    List<User> userList = gson.fromJson(jsonArray, new TypeToken<List<User>>() {}.getType()); 
    String string = new Gson().toJson(userList); 
    JsonArray jsonArray = new Gson().toJsonTree(userList, new TypeToken<List<User>>() {}.getType()).getAsJsonArray();
    JsonArray jsonArray = new JsonParser().parse(string).getAsJsonArray();

注意

基本概念

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

  • 1
  • 2
  • 3
  • 4
  • 澳门新葡萄京娱乐场,5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

请注意,在文章中我们将互换格式化或序列化的术语。

Gson解决的问题

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

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

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

  4. 支持任意的复杂对象

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


澳门新葡萄京娱乐场 1

下面列出的所有代码都可以在这里找到: http://java-creed-examples.googlecode.com/svn/gson/Gson
Serialiser
Example/ 。大多数例子不会包含完整的代码,可能会忽略和要讨论的例子不相关的片段。读者可以从上面的链接下载查看完整的代码。

Gson处理对象的几个重要点

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

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

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

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

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

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


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

简单的例子

考虑下面这个 Java 对象。

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 对象。

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

Gson 不需要任何特殊配置就可以序列化 Book 类。Gson 使用 Java 字段名称作为
JSON 字段的名称,并赋予对应的值。如果仔细地看一下上面的那个 JSON
示例会发现, ISBN 字段包含一个减号:isbn-10 和
isbn-13。不幸的是,使用默认配置不能将这些字段包含进来。解决问题的办法之一就是使用注解,就像在这篇文章中描述的那样:Gson
注解示例。使用注解可以自定义
JSON
字段的名称,Gson将会以注解为准进行序列化。另一个方法就是使用 JsonSerialiser (Java
Doc),如下所示:

package com.javacreed.examples.gson.part1;

import java.lang.reflect.Type;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public class BookSerialiser implements JsonSerializer {

    @Override
    public JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) {
        final JsonObject jsonObject = new JsonObject();
        //The serialisation code is missing

        return jsonObject;
    }
}

上面的例子还缺失了重要部分,需要通过补充序列化代码来完善。在添加更多代码使其变得复杂之前,我们先来理解下这个类。

JsonSerializer
接口要求类型是将要进行序列化的对象类型。在这个例子中,我们要序列化的
Java 对象是 Book。serialize()方法的返回类型必须是一个 JsonElement
(Java
文档)类型的实例。详见这篇文章:Gson
反序列化实例,下面列出了JsonElement
四种具体实现类型:

  • JsonPrimitive (Java
    Doc) ——
    例如一个字符串或整型
  • JsonObject (Java
    Doc) ——
    一个以 JsonElement 名字(类型为 String)作为索引的集合。类似于
    Map<String,JsonElement>集合(Java
    Doc)
  • JsonArray (Java
    Doc)——
    JsonElement
    的集合。注意数组的元素可以是四种类型中的任意一种,或者混合类型都支持。
  • JsonNull (Java
    Doc) ——
    值为null

JsonElement的类型

澳门新葡萄京娱乐场 2

上面这张图片展示了 JsonElement 的所有类型。可以把 JsonObject 看作值为
JsonElement 的键值对集合。因此,这些值可以是另外四种对象。

下面是序列化的完整实例:

package com.javacreed.examples.gson.part1;

import java.lang.reflect.Type;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public class BookSerialiser implements JsonSerializer {

    @Override
    public 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;
    }
}

我们在这里添加了一些代码。在理解整个图片的含义前,我们先把它拆成一个个小的部分,先来解释下每部分的含义。

如果要序列化这个 Java 对象,首先需要创建一个 JsonElement
实例。例子中是返回了一个 JsonObject 实例来代表 Book 对象,如下所示:

final JsonObject jsonObject = new JsonObject();

该对象使用我们设置的字段名称进行填充,如下:

// The variable 'book' is passed as a parameter to the serialize() method
    final JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("title", book.getTitle());
    jsonObject.addProperty("isbn-10", book.getIsbn10());
    jsonObject.addProperty("isbn-13", book.getIsbn13());

使用 addProperty() 方法 (Java
Doc))可以添加任何
Java 原始类型以及String和Number。注意此处的 name
必须是唯一的,否则会被前一个覆盖掉。可以将其看做是一个将字段名作为值索引的
Map。

更复杂的对象,比如 Java
对象或数组就不能使用上面的方法来添加了。JsonObject 有另外一个 add()
方法,可以用来作为替代,如下所示:

// The variable 'book' is passed as a parameter to the serialize() method
    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);

首先创建一个 JsonArray 对象,然后将所有 authors 添加进去。和 Java
不同的是,初始化 JsonArray
时不需要指定数组的大小。事实上,抛开这个类的名字不看,可以将 JsonArray
类更多地看做是一个 list 而非 array。最后将 jsonAuthorsArray  添加到
jsonObject
中。此处也可以在给 jsonAuthorsArray 添加元素之前,将其添加到 jsonObject 中。

在调用该序列化方法之前,我们需要将其注册到 Gson 中:

package com.javacreed.examples.gson.part1;

import java.io.IOException;

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 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 JSON
    final String json = gson.toJson(javaPuzzlers);
    System.out.println(json);
  }
}

通过注册我们自己实现的序列化器,告诉 Gson 无论什么时候序列化 Book
类型的对象都使用该序列化器进行序列化。

在上面例子中,通过调用 set prettying printing 方法还告诉了 Gson 对生成的
JSON 对象进行格式化,如下所示:

gsonBuilder.setPrettyPrinting();

虽然这对于调试和教程非常有用,但请不要在生产环境中这样用,因为可能会因此产生更大的
JSON 对象(文本的大小)。除此之外,由于 Gson 必须要格式化 JSON
对象,即对其进行相应的缩进,pretty printing 会有一些性能方面的消耗。

运行上面的代码可以得到预期的 JSON
对象。对我们的第一个例子做个总结,即怎样自定义 Gson 序列化器将 Java
对象序列化为 JSON 对象。下一章将会讲到怎样使用 Gson 序列化嵌套对象。

Gson中的一些注解

 

嵌套对象

接下来的例子将会描述怎么序列化嵌套对象。所谓嵌套对象是指在其它对象内部的对象。在此我们将会引入一个新的实体:author。形成了这样一个包含
title 和 ISBN 连同 author 列表的
book。在这个例子中将会得到一个包含新实体的 JSON
对象,与前面的JSON对象不同,就像下面那样:

{
  "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases",
  "isbn": "032133678X",
  "authors": [
    {
      "id": 1,
      "name": "Joshua Bloch"
    },
    {
      "id": 2,
      "name": "Neal Gafter"
    }
  ]
}

注意,前一个例子中 authors 只是一个简单的字符数组:

"authors": [
    "Joshua Bloch",
    "Neal Gafter"
  ]

这个例子中的 authors 是一个 JSON 对象,而不仅仅只是一个基本类型。

{
      "id": 1,
      "name": "Joshua Bloch"
    }

author 的 JSON对象有一个 id 和一个 name字段。下面是 Author 类。

package com.javacreed.examples.gson.part2;

public class Author {

  private int id;
  private String name;

  // Methods removed for brevity

}

这个类非常简单,由两个字段组成,并且都是原始类型。Book 类被修改为使用
Author 类,如下所示:

package com.javacreed.examples.gson.part2;

public class Book {

  private Author[] authors;
  private String isbn;
  private String title;

  // Methods removed for brevity

}

author 字段从一个 integer 数组变成了一个 Author 数组。因此必须修改下
BookSerialiser 类来兼容这一改变,如下:

package com.javacreed.examples.gson.part2;

import java.lang.reflect.Type;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public class BookSerialiser implements JsonSerializer<Book> {

  @Override
  public JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) {
    final JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("title", book.getTitle());
    jsonObject.addProperty("isbn", book.getIsbn());

    final JsonElement jsonAuthros = context.serialize(book.getAuthors());
    jsonObject.add("authors", jsonAuthros);

    return jsonObject;
  }
}

authors 的序列化由 context(作为 serialize()
方法的一个参数被传进来,是 JsonSerializationContext 的实例)
来完成。context 将会序列化给出的对象,并返回一个 JsonElement。同时
context
也会尝试找到一个可以序列化当前对象的序列化器。如果没有找到,其将会使用默认的序列化器。目前,我们还不会为
Author 类实现一个序列化器,仍然会使用默认实现作为替代。

package com.javacreed.examples.gson.part2;

import java.io.IOException;

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 BookSerialiser());
    gsonBuilder.setPrettyPrinting();
    final Gson gson = gsonBuilder.create();

    final Author joshuaBloch = new Author();
    joshuaBloch.setId(1);
    joshuaBloch.setName("Joshua Bloch");

    final Author nealGafter = new Author();
    nealGafter.setId(2);
    nealGafter.setName("Neal Gafter");

    final Book javaPuzzlers = new Book();
    javaPuzzlers.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases");
    javaPuzzlers.setIsbn("032133678X");
    javaPuzzlers.setAuthors(new Author[] { joshuaBloch, nealGafter });

    final String json = gson.toJson(javaPuzzlers);
    System.out.println(json);
  }
}

上面的例子创建并配置 Gson 使用自定义的 BookSerialiser
进行序列化。我们创建了两个 author 对象和一个 book 对象,并序列化该 book
对象。这样将会得到在章节开始时展示的 JSON 对象。

完整起见,下面是一个 Author 类的序列化器:

package com.javacreed.examples.gson.part2;

import java.lang.reflect.Type;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public class AuthorSerialiser implements JsonSerializer<Author> {

  @Override
  public JsonElement serialize(final Author author, final Type typeOfSrc, final JsonSerializationContext context) {
    final JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("id", author.getId());
    jsonObject.addProperty("name", author.getName());

    return jsonObject;
  }
}

上面的序列化器并没有引入什么新的特性,因此不需要再多做解释。如果想要使用这个新的序列器,需要将其注册到
GsonBuilder (Java
Doc) 中。

本章对嵌套对象的序列化做了总结。可以将嵌套对象的序列化交给 context
处理,其在序列化时会顺带尝试找到一个合适的序列化器,并返回相应的
JsonElement。下一章也是最后一章将会讲如何处理对象引用的序列化。

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字段中。

 

对象引用

一个对象对其它对象的引用叫做对象引用,book 和 author
类之间的关系就是这样。同一个 author 可以有多本 book。例如 author Joshua
Bloch(Author at
Amazon)不止一本
book。在使用序列化器描述之前,我们将会清除重复的 author。

考虑下面这个例子:

package com.javacreed.examples.gson.part3;

import java.io.IOException;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Example1 {

  public static void main(final String[] args) throws IOException {
    // Configure GSON
    final GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.setPrettyPrinting();
    final Gson gson = gsonBuilder.create();

    final Author joshuaBloch = new Author();
    joshuaBloch.setId(1);
    joshuaBloch.setName("Joshua Bloch");

    final Author nealGafter = new Author();
    nealGafter.setId(2);
    nealGafter.setName("Neal Gafter");

    final Book javaPuzzlers = new Book();
    javaPuzzlers.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases");
    javaPuzzlers.setIsbn("032133678X");
    javaPuzzlers.setAuthors(new Author[] { joshuaBloch, nealGafter });

    final Book effectiveJava = new Book();
    effectiveJava.setTitle("Effective Java (2nd Edition)");
    effectiveJava.setIsbn("0321356683");
    effectiveJava.setAuthors(new Author[] { joshuaBloch });

    final Book[] books = new Book[] { javaPuzzlers, effectiveJava };

    final String json = gson.toJson(books);
    System.out.println(json);
  }
}

两个作者和两本书,其中一个作者在两本书中都有。注意,有两个 author
对象而不是三个,代表 Joshua Bloch 的实例被两个 book
对象共享。最后注意,我们故意没有使用任何自定义的序列化器。下面是执行上面代码的结果。

[
  {
    "authors": [
      {
        "id": 1,
        "name": "Joshua Bloch"
      },
      {
        "id": 2,
        "name": "Neal Gafter"
      }
    ],
    "isbn": "032133678X",
    "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases"
  },
  {
    "authors": [
      {
        "id": 1,
        "name": "Joshua Bloch"
      }
    ],
    "isbn": "0321356683",
    "title": "Effective Java (2nd Edition)"
  }
]

得到了两个 book 类型的 JSON 和三个 author 类型的
JSON。而对于author:Joshua Bloch 是重复的。

 {
        "id": 1,
        "name": "Joshua Bloch"
      }

这会使得 JSON 对象明显变大,尤其是对更复杂的对象。理想情况下,book 的
JSON 对象应该只包含 author 的 id 而不是整个对象。这类似于关系型数据库中
book 表有一个外键关联到 author 表。

Book 类将会被修改为包含一个只返回 author 的 id 的方法,如下:

package com.javacreed.examples.gson.part3;

public class Book {

  private Author[] authors;
  private String isbn;
  private String title;

  public Author[] getAuthors() {
    return authors;
  }

  public int[] getAuthorsIds() {
    final int[] ids = new int[authors.length];
    for (int i = 0; i < ids.length; i++) {
      ids[i] = authors[i].getId();
    }
    return ids;
  }// Other methods removed for brevity

}

当序列化 book 时,使用 author 的 id 代替整个 author 对象,如下:

package com.javacreed.examples.gson.part3;

import java.lang.reflect.Type;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

public class BookSerialiser implements JsonSerializer {

  @Override
  public JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) {
    final JsonObject jsonObject = new JsonObject();
    jsonObject.addProperty("title", book.getTitle());
    jsonObject.addProperty("isbn", book.getIsbn());

    final JsonElement jsonAuthros = context.serialize(book.getAuthorsIds());
    jsonObject.add("authors", jsonAuthros);

    return jsonObject;
  }
}

下面是使用这个序列化器得到的结果:

[
  {
    "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases",
    "isbn": "032133678X",
    "authors": [
      1,
      2
    ]
  },
  {
    "title": "Effective Java (2nd Edition)",
    "isbn": "0321356683",
    "authors": [
      1
    ]
  }
]

现在我们使用 author 的 id 代替了整个
author。这一做法使得其比前一个有更小的空间占用。对于更大的对象将产生巨大的影响。

这个例子是整篇文章关于序列化的总结。从中我们学会了怎么使用默认或自定义的序列化选项,将
Java 对象序列化为 JSON 字符串。

2 @Expose注解

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

public class Account {

  @Expose(deserialize = false)
  private String accountNumber;

  @Expose
  private 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();

关于GSON的入门级使用,这里就不提了,如有需要可以看这篇博文 《Google
Gson的使用方法,实现Json结构的相互转换》 ,写的很好,通俗易懂。

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.2
    account.setTeamName("Zejtun Corinthians");
    account.setCountry("Malta"); // Until version 0.9

    final 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"}

我为什么写这篇文章呢?因为前几晚跟好友 xiasuhuei321 探讨了一下GSON解析复杂的JSON的时候,能不能只解析源数据中的数组,甚至只解析数组的某一部分。探讨了二十分钟,得出结论:没用过,不知道。

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当然为我们提供了对应的解决方案

所以今天特地研究了一下,发现真的So
Easy!之前想复杂了,学习的过程中,发现有五种方式分别搞定不同情况的JSON数组,也就是今天说的五大招!

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方法等

}

在介绍之前先来个约定,比如下面的这个JSON:

2 序列化方案2

利用JsonSerializer

public class BookSerialiser implements JsonSerializer {

    @Override
    public 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中的添加方法:

澳门新葡萄京娱乐场 3

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

  • 同样需要配置,

// Configure GSON
    final 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 JSON
    final String json = gson.toJson(javaPuzzlers);
    System.out.println(json);

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


"muser": [
    {
      "name": "zhangsan",
      "age": "10",
      "phone": "11111",
      "email": "11111@11.com"
    },
    ...
]

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实体类,

  • 这里的 “muser” ,也就是数组的名称,称它为数据头,防止跟里面的 字段 有歧义;
  • 如果没有数据头,那就叫它纯数据,或者纯数组数据;
  • 代码中用到的 JsonArray/JsonObject 等熟悉的类全部来自 GSON 。
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方法等

}

澳门新葡萄京娱乐场 4

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

开始过招吧!

2 反序列化方案2

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

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;
  }
}

和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 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);
    }

第一招 A

参考链接

翻译原文,根据原文做出了较大改动。
1 SIMPLE GSON
EXAMPLE
2 GSON DESERIALISER
EXAMPLE
3 GSON ANNOTATIONS
EXAMPLE
4 GSON SERIALISER
EXAMPLE
5 GSON TYPEADAPTER
EXAMPLE
6 GSON TYPEADAPTER EXAMPLE SERIALISE LARGE
OBJECTS

另附:
你真的会用Gson吗?Gson使用指南(一)系列文章

没有数据头的纯数组JSON如何解析?

根据约定,也就是这个 JSON
里面只有一个数组(JsonArray),而且这个数组没有名字,比如像下面这样的:

[
  {
    "name": "zhangsan",
    "age": "10",
    "phone": "11111",
    "email": "11111@11.com"
  },
  {
    "name": "lisi",
    "age": "20",
    "phone": "22222",
    "email": "22222@22.com"
  },
  ...
]

这里其实是最简单的一种 JSON 数组格式,强大的 GSON 可以直接解析成一个
List
。但在这里我先不直接解析,就用比较老实的方法去解析,因为需要引出两个东西。

首先我们需要建立一个Bean对象,注意变量名要跟字段名称一致,没什么好说的:

public class UserBean {
    //变量名跟JSON数据的字段名需要一致
    private String name ;
    private String age;
    private String phone;
    private String email;
    ...
}

下面这是解析过程,先看代码:

/**
 * 解析没有数据头的纯数组
 */
private void parseNoHeaderJArray() {
    //拿到本地JSON 并转成String
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_1);

    //Json的解析类对象
    JsonParser parser = new JsonParser();
    //将JSON的String 转成一个JsonArray对象
    JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray();

    Gson gson = new Gson();
    ArrayList<UserBean> userBeanList = new ArrayList<>();

    //加强for循环遍历JsonArray
    for (JsonElement user : jsonArray) {
        //使用GSON,直接转成Bean对象
        UserBean userBean = gson.fromJson(user, UserBean.class);
        userBeanList.add(userBean);
    }
    mainLView.setAdapter(new UserAdapter(this, userBeanList));
}

从代码中可以看出解析的步骤如下:

  • 无论 JSON 来自本地还是网络获取,都要先将 JSON 转成 String ;
  • 需要一个 JSON 解析类对象将JSON的字符串转成 JsonArray
    ,前提是我们知道 JSON 中只有纯数组;
  • 循环遍历 JsonArray ,并用 GSON 解析成相应的对象。

代码本身不难,容易看懂,但前面说到,这里我故意这样写,因为需要说两个东西:

1、JsonParse

从名称我们就可以看出,这是一个解析类。没错,它可以把 JSON
数据分别通过 getAsJsonObject 和 getAsJsonArray 解析成 JsonObject 和 JsonArray 。这跟普通的解析
JSON 差不多,不展开说。

2、JsonElement

这个类我是第一次见,它是一个抽象类,代表 JSON
串中的某一个元素,可以是 JsonObject/JsonArray/JsonPrimitive/… 中的任何一种元素。

所以在上面的代码中,我们可以看到它能把 JsonArray 中的每一个元素转成 JsonObject ,甚至说它本身就是 JsonObject 。

好了,就为了说这两个东西。记住,后面将会用到。

来看一下运行的图吧,很简单的东西,后面的二三都是这样的效果,就不重复贴图了:

第二招 Q

有数据头的纯数组数据该怎么解析?

内容跟上面的 JSON
一模一样,只不过加了一个名称 “muser” ,也就是约定好的 数据头 :

{
  "muser": [
    {
      "name": "zhangsan",
      "age": "10",
      "phone": "11111",
      "email": "11111@11.com"
    },
    {
      "name": "lisi",
      "age": "20",
      "phone": "22222",
      "email": "22222@22.com"
    },
    ...
  ]
}

有人说,这还不简单,在第一招中的 getAsJsonArray 加一个字符串就是咯,就像这样:

JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray("muser");

思路是对的,但是不要忘了,数组装在一个 {
} 括起来的 JsonObject 里。还记得上面的 JsonParse 么,它的 getAsJsonObject 可以做到这点,所以代码就是这样啦,很简单就不再解释了:

/**
 * 解析有数据头的纯数组
 */
private void parseHaveHeaderJArray() {
    //拿到本地JSON 并转成String
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_2);

    //先转JsonObject
    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
    //再转JsonArray 加上数据头
    JsonArray jsonArray = jsonObject.getAsJsonArray("muser");

    Gson gson = new Gson();
    ArrayList<UserBean> userBeanList = new ArrayList<>();

    //循环遍历
    for (JsonElement user : jsonArray) {
        //通过反射 得到UserBean.class
        UserBean userBean = gson.fromJson(user, new TypeToken<UserBean>() {}.getType());
        userBeanList.add(userBean);
    }
    mainLView.setAdapter(new UserAdapter(this, userBeanList));
}

注意,这里又引出了一个东西: TypeToken ,它是什么呢?

3、TypeToken

这个东西很有意思,本来我不知道到是干嘛的,看了看源码,看不懂。后来无意发现它所在的包:

import com.google.gson.reflect.TypeToken;

哎哟我去, reflect 这不是反射么,一下子就明白了。没错,它其实是一个匿名内部类,看一下官方解释:

GSON 提供了 TypeToken 这个类来帮助我们捕获(capture)像 List
这样的泛型信息。Java编译器会把捕获到的泛型信息编译到这个匿名内部类里,然后在运行时就可以被
getType() 方法用反射的 API 提取到。

解释的很官方,实际上就是一句 通俗但不严谨 的话,它将泛型 T 转成 .class 。比如上面的 TypeToken 经过 getType() 后就是 UserBean.class 。

好了,说到这里基本铺垫就完成了,再次强调一下:

对于上面的 JSON 完全可以直接通过 GSON 转成 List
,不用这么麻烦,我只是为了引出3个小知识。

第三招 W

有数据头的复杂数据该如何解析呢?

简单的说完了,铺垫也铺完了,来看一看复杂的吧:

{
  "code": 200,
  "msg": "OK",
  "muser": [
    {
      "name": "zhangsan",
      "age": "10",
      "phone": "11111",
      "email": "11111@11.com"
    },
    {
      "name": "lisi",
      "age": "20",
      "phone": "22222",
      "email": "22222@22.com"
    },
    ...
  ]
}

这里就不再是纯数组数据了,还有两个凑数的不知道干嘛用的字段,这里也有数据头,之前用的是笨方法,现在来真正见识一下GSON的威力吧。

第一步根据 JSON 建立 Bean ,注意这里的 Bean 是返回所有字段,因为 GSON
能直接解析成 List ,所以 Bean 是下面这样的,同样把占地方的 get/set
省略:

/**
 * Created by xiarui on 2016/8/30.
 * 返回所有结果的Bean
 */
public class ResultBean {
    //注意变量名与字段名一致
    private int code;
    private String msg;
    private List<UserBean> muser;

    public class UserBean{
        private String name ;
        private String age;
        private String phone;
        private String email;
        ...
    }
    ...
}

注意,这个 ResultBean 里面有一个 UserBean 。
它虽然跟上面第一第二招虽然内容一样,但是作用不一样,这是作为 JsonArray 解析后存入 List 中的对象。

算了,有点拗口,直接上代码吧:

/**
 * 有消息头 复杂数据 常规方式
 */
private void parseComplexJArrayByCommon() {
    //拿到Json字符串
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3);
    //GSON直接解析成对象
    ResultBean resultBean = new Gson().fromJson(strByJson,ResultBean.class);
    //对象中拿到集合
    List<ResultBean.UserBean> userBeanList = resultBean.getMuser();
    //展示到UI中
    mainLView.setAdapter(new ResultAdapter(this, userBeanList));
}

没错,就是这么四句话搞定第一二招的内容。看出GSON的强大了吧,当然如果有人想不开只写一句话的话:

mainLView.setAdapter(new ResultAdapter(this,new Gson().fromJson(JsonToStringUtil.getStringByJson(this,R.raw.juser_3),ResultBean.class).getMuser()));

我也是没意见的,不过请对自己好一点,谢谢。

第四招 E

只想解析复杂JSON中的数组或数组中的某部分内容怎么办?

好了,来到重点了,这也是跟好友 xiasuhuei321 没有讨论出来的情况。

还是上面的JSON数据,这里为了篇幅就不贴重复代码了,假如我只想取 “muser” 这个数组中的年龄(age)大于30岁的怎么办?

OK,当然可以先全部解析,再从 List
中取。那假如我有一万条数据呢?全部解析不是很麻烦呢?

所以一个思路就是第一二招中说的: 遍历!

OK,你会问先遍历还不是要读一万条,是的,还是要读一万条,但是假如我要把这些存入数据库呢?假如一万条数据中只有一条符合条件,难道我先存一万条,再从数据库中查询么?

当然这种情况是极端情况,但也说明了一个问题,不能所有情况下都先全部解析,假如有一万个字段,Bean还得写多长…可怕。

现在来说一下完整的思路,也是我学习中思考的过程:

  • 第一点肯定就是刚才提到的遍历,这个很好理解,所以我们先要取这一个数组(JsonArray),那么如何取呢?还记得之前提到的 JsonParse 么,它的 getAsJsonArray() 可以传入 数据头 拿到数组,当然不要忘了最外面一层是个 JsonObject 。

    //最外层
    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
    //需要遍历的数组
    JsonArray jsonArray = jsonObject.getAsJsonArray("muser");
    
  • 拿到数组以后,我们就可以遍历了,经过第一二招的洗礼,相信在遍历上,应该没什么问题了,使用的还是之前提到的 JsonElement 。

    //循环遍历数组
    for (JsonElement user : jsonArray) {
        UserBean userBean = new Gson().fromJson(user, new TypeToken<UserBean>() {}.getType());
        //根据条件过滤
        if (Integer.parseInt(userBean.getAge()) > 30) {
            userBeanList.add(userBean);
        }
    }
    
  • 上面的代码很简单,也用到了之前提到的 TypeToken ,什么意思就不用解释了吧。

好了,完整的代码如下:

/**
 * 有数据头 复杂数据 截取方式
 */
private void parseComplexJArrayByDirect() {
    //拿到JSON字符串
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3);
    List<UserBean> userBeanList = new ArrayList<>();

    //拿到数组
    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
    JsonArray jsonArray = jsonObject.getAsJsonArray("muser");

    //循环遍历数组
    for (JsonElement user : jsonArray) {
        UserBean userBean = new Gson().fromJson(user, new TypeToken<UserBean>() {
        }.getType());
        //根据条件过滤
        if (Integer.parseInt(userBean.getAge()) > 30) {
            userBeanList.add(userBean);
        }
    }
    mainLView.setAdapter(new UserAdapter(this, userBeanList));
}

运行的结果图如下:

可以看到,现在我们做到了只取 JSON
数据中数组中某一部分了。那么扩展一下,只取 JSON
数据中的某一个数组中的某一个字段呢?当然可以实现,不过还是留给大家自己思考吧,当然下面反人类的第五招也是可以解决这个问题的。

第五招 R

如果一个 JSON 数据很很很复杂怎么解析?

什么叫做复杂,这里我简单写了个比较复杂的,有数据头,一层嵌套一层,我还没有写数组呢:

{
  "group": {
    "user": {
      "name": "张三",
      "age": "10",
      "phone": "11111",
      "email": "11111@11.com"
    },
    "info": {
      "address": "北京",
      "work": "Android Dev",
      "pay": "10K",
      "motto": "先定一个小目标,比如我先赚一个亿"
    }
  }
}

三种方式解析:

  • 第三招,全部解析出来;
  • 第四招,要什么解析什么;
  • 第五招,反人类的 JsonReader 。

至于为什么反人类,不好说。大家看代码就知道了,代码很简单,跟 XML 的解析差不多,是根据节点来的,至于怎么用,还是那句话直接看代码吧,确实处理起来逻辑清晰,但是代码量上,真的不敢恭维。

只贴代码不作解释,如想详细了解,看文末链接。

/**
 * 通过JsonReader的方式去解析
 */
private void parseComplexJArrayByReader() throws IOException {
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_4);
    JsonReader reader = new JsonReader(new StringReader(strByJson));
    try {
        reader.beginObject();
        String tagName = reader.nextName();
        if (tagName.equals("group")) {
            //读group这个节点
            readGroup(reader);
        }
        reader.endObject();
    } finally {
        reader.close();
    }
}

/**
 * 读group这个节点
 *
 * @param reader JsonReader
 */
private void readGroup(JsonReader reader) throws IOException {
    reader.beginObject();
    while (reader.hasNext()) {
        String tagName = reader.nextName();
        if (tagName.equals("user")) {
            readUser(reader);
        } else if (tagName.equals("info")) {
            readInfo(reader);
        }
    }
    reader.endObject();
}

/**
 * 读用户基本消息 user节点
 *
 * @param reader JsonReader
 */
private void readUser(JsonReader reader) throws IOException {
    reader.beginObject();
    while (reader.hasNext()) {
        String tag = reader.nextName();
        if (tag.equals("name")) {
            String name = reader.nextString();
            nameText.setText(name);
        } else if (tag.equals("age")) {
            String age = reader.nextString();
            ageText.setText(age);
        } 
        ...
        else {
            reader.skipValue();//忽略
        }
    }
    reader.endObject();
}

/**
 * 读用户其他消息 info节点
 *
 * @param reader JsonReader
 */
private void readInfo(JsonReader reader) throws IOException {
    reader.beginObject();
    while (reader.hasNext()) {
        String tag = reader.nextName();
        if (tag.equals("address")) {
            String address = reader.nextString();
            addressText.setText(address);
        } else if (tag.equals("work")) {
            String work = reader.nextString();
            workText.setText(work);
        } 
        ...
        else {
            reader.skipValue();//忽略
        }
    }
    reader.endObject();
}

上面代码有省略,因为好长…运行图如下:

五招过完,多谢指教!

总结

以上几乎就是 JSO
N数组的所有情况了,这五招也几乎能全部搞定!不得不说,GSON
确实比较强大,强大在于可以将 JSON
直接解析成对象,比以前的手动去解析方便太多,当然 fastJson
也能实现这点,但是这东西还是官方的用的顺手。

在学习的过程中,也是一步一步来的,所以文章也是学习的过程,从简单的例子学到关键内容,再解决复杂情况。由于文章写得仓促,如有疑问或错误,欢迎交流与指正,谢谢!

参考资料

灵活组装Json的数据使用Gson的JsonParser和JsonReader解析Json详解例子

使用Gson解析复杂的json数据 –
tkwxty

JsonElement的简单说明 –
chunqiuwei

Java进阶(四)Java反射TypeToken解决泛型运行时类型擦除的有关问题解决

项目源码

GsonArrayDemo – IamXiaRui –
Github

 

String、JsonObject、JavaBean 互相转换
    User user = new Gson().fromJson(jsonObject, User.class);
    User user = new Gson().fromJson(string, User.class);
    String string = new Gson().toJson(user);
    JsonObject jsonObject = new Gson().toJsonTree(user).getAsJsonObject(); 
    JsonObject jsonObject = new JsonParser().parse(string).getAsJsonObject();
String、JsonArray、List互相转换
    List<User> userList = gson.fromJson(string, new TypeToken<List<User>>() {}.getType()); 
    List<User> userList = gson.fromJson(jsonArray, new TypeToken<List<User>>() {}.getType()); 
    String string = new Gson().toJson(userList); 
    JsonArray jsonArray = new Gson().toJsonTree(userList, new TypeToken<List<User>>() {}.getType()).getAsJsonArray();
    JsonArray jsonArray = new JsonParser().parse(string).getAsJsonArray();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

澳门新葡萄京娱乐场 5

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注