Gson-Java-Json序列化和反序列化

背景介绍

Google的Gson库,Gson是一个非常强大的库,可以将JSON格式的数据转化为Java对象,也支持将Java对象转成JSON数据格式

Maven项目添加

<dependencies>
    <dependency>
       <groupId>com.google.code.gson</groupId>
       <artifactId>gson</artifactId>
      <version>2.8.0</version>
       <scope>compile</scope>
    </dependency>
</dependencies>

实例代码

public class Translate {
    public static void main(String[] args) {
        UserSample userSample = new UserSample();
        userSample.setAge(24);
        userSample.setDeveloper(true);
        userSample.setEmail("1085669445@qq.com");
        userSample.setName("gaohu");
        //对象序列化为JSon
        Gson gson = new Gson();
        String sout = gson.toJson(userSample);
        System.out.println(sout);
        //字符串反序列化为对象
        String userJson =      {'age':26,'email':'norman@futurestud.io','isDeveloper':true,'name':'Norman'}";
        //通过 fromJson() 方法将JSON映射成一个 Java 对象:
        UserSample object = gson.fromJson(userJson, UserSample.class);
        System.out.println(object);

    }

}

输出

{"name":"gaohu","email":"1085669445@qq.com","age":24,"isDeveloper":true}
 com.ly.flight.ticketsell.biz.service.test.UserSample@7fbe847c

注意第二个参数的传递,否则,Gson 不知道将 JSON 转换成什么类型。Debug模式可以看到

Gson - Arrays 和 Lists 对象映射

数组和列表对象的映射

Array和List差异

在Java中两者实现方式不同,使用哪一种数据类型取决于你的实际需求,但在序列化这个问题上,Gson并不关心这两种数据结构的具体实现

在Json数据格式中,不存在数组等结构,只是Java 的具体实现使这两种数据类型有很大不同,但是在上层它们表示出相同的结构,接下来,我们将重新理解这两种数据类型。

Array和List序列化

model

public class RestaurantWithMenu { 
    String name;

    List<RestaurantMenuItem> menu;
    //RestaurantMenuItem[] menu; // alternative, either one is fine
}

public class RestaurantMenuItem { 
    String description;
    float price;
}

通过嵌套对象的方式即可,在 Java Model 中包含要映射变量的引用就可以了,要注意名字和JSON中字段名相同。

JSON 格式如下:

{
    "name": "Future Studio Steak House",
    "menu": [
    ...
    ]
}

与嵌套对象类似,我们没有 menu 的直接值,相反,JSON 中通过 “[]” 来包含一个对象,如上所述,在 JSON 数据中,数组和 List 结构是没有区别的。

menu 中包含一些对象,在我们那的 model 中,menu 只是其中的一个变量,我们先来手动生成一个完整的 JSON 数据。

通过下面这种方式,我们来模拟一个完整的 restaurant 数据:

List<RestaurantMenuItem> menu = new ArrayList<>();
menu.add(new RestaurantMenuItem("Spaghetti", 7.99f));
menu.add(new RestaurantMenuItem("Steak", 12.99f));
menu.add(new RestaurantMenuItem("Salad", 5.99f));

RestaurantWithMenu restaurant = new RestaurantWithMenu("Future Studio Steak House", menu);

Gson gson = new Gson();
String restaurantJson = gson.toJson(restaurant);
{
    "menu": [
    {
        "description": "Spaghetti",
        "price": 7.99
    },
    {
        "description": "Steak",
        "price": 12.99
    },
    {
        "description": "Salad",
        "price": 5.99
        }
    ],
    "name": "Future Studio Steak House"
}

如我们预料,我们得到了想要的数据,按照字母顺序,menu 排在了name 的前面,根据 “[]” 标志 List 开始,根据 “{}” 标志对象开始。

但是我们并不是总是将 List 嵌套在对象中,我们可能会直接得到一个 List,Gson 也是支持直接序列化一个 List。

String menuJson = gson.toJson(menu);

输出

[
    {
        "description": "Spaghetti",
        "price": 7.99
    },
    {
        "description": "Steak",
        "price": 12.99
    },
    {
        "description": "Salad",
        "price": 5.99
    }
]

来看下数据中的不同,JSON 中的 “[“ 表示一个对象列表开始,”{“ 表示一个对象开始了,我们应该记住 JSON 数据中格式差别。

数组和List反序列化

首先看解析成数组,通过 Gson 的 gson.fromJson 方法,我们很简单的将 GSON 解析成数组,注意这里传递的参数是 Founder[].class 而不是Founder.class ,如下:

String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";

Gson gson = new Gson();
Founder[] founderArray = gson.fromJson(founderJson, Founder[].class);

Lists

实际开发中,我们更多的是转成一个 ArrayList,但是,我们不能像解析数组那样传入 List,为了让Gson知道我们要解析的数据类型,我们必须传递给它一个Type,内部根据 TypeToken 来区分要解析的类型。例如:

Type founderListType = new TypeToken<ArrayList<Founder>>(){}.getType();
String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";

Gson gson = new Gson();

Type founderListType = new TypeToken<ArrayList<Founder>>(){}.getType();

List<Founder> founderList = gson.fromJson(founderJson, founderListType);

列表存在 Model 类中的一个好处就是,我们在使用Gson解析时不再需要传递 TypeToken,直接穿入类即可。

 String generalInfoJson = "{'name': 'Future Studio Dev Team',  'meun': [{'description': 'Christian', 'price': 1 }, {'description': 'Marcus','price': 3 }, {'description': 'Norman','price': 2 }]}";
        ReStaurantMenu reStaurantMenu = gson.fromJson(generalInfoJson, ReStaurantMenu.class);
        System.out.println(reStaurantMenu);

List 中嵌套 List

Gson 也可以解析 List 中嵌套 List 数据结构,看下面这个例子,例如:

public class GeneralInfo {
    String name;
    String website;
    List<FounderWithPets> founders;
}

public class FounderWithPets {
    String name;
    int flowerCount;
    List<Pet> pets;
}

public class Pet {
    String name;
    List<Toy> toys;
}

Java Map 序列化

在介绍使用 Gson 解析一些基本数据结构之后,我们来看下如何使用Gson 来序列化和反序列化 Java 中的 Map 数据类型。

实例 HashMap

HashMap<String, List<String>> employees = new HashMap<>();
employees.put("A", Arrays.asList("Andreas", "Arnold", "Aden"));
employees.put("C", Arrays.asList("Christian", "Carter"));
employees.put("M", Arrays.asList("Marcus", "Mary"));

输出

{"A":["Andres","Arnold","Aden"],"B":["Christian","Carter"],"C":["Marus","Mary"]}

正如 Java Map 结构一样,每个 Key 对应这个一个集合。

Java Map 反序列化

和上面 JSON 数据对比,我们发现有些不一样,这里的 key 是变化的,而不像 List 那样是固定的字段名

{
    "1$": {
       "amount": 1,
        "currency": "Dollar"
    },
    "2$": {
       "amount": 2,
        "currency": "Dollar"
    },
    "3€": {
        "amount": 3,
        "currency": "Euro"
    }
}

Json 数据中包含三个对象,每个对象有自己的值,但是我们发现 Json 数据更像一个 Map 结构1​ ,3€ 是key

以下是区分 JSON 数据类型的一些简单的方法:

根据你的文档解释或者应用场景键和值是否是一种类型键和值是否是动态的我们假设本例子就是一个map结构的数据,之前我们使用TypeToken来标志过list类型,这里我们需要创建一个map类型的TypeToken类型。


 上一篇
java正则表达式 java正则表达式
正则表达式是对字符串操作的一种逻辑公式,用一些特定字符及字符组合,组成一个规则字符串.
2017-05-09
下一篇 
Java8新特性 Java8新特性
Lambda表达式与Functional接口、扩展注解的支持、Stream流处理方式.
2017-03-23
  目录