在开发过程中,我们经常需要将数据进行序列化和反序列化。序列化是将对象转换为可传输或可存储的格式,而反序列化则是将序列化后的数据重新还原成对象。针对数组、集合和映射这些常见的数据结构,Google 提供了一个强大而灵活的 Java 库——Gson。本文将介绍如何使用 Gson 进行数组、集合和映射的序列化与反序列化。

引入Gson库

首先,我们需要在项目中引入 Gson 库。可以通过 Maven 或 Gradle 配置文件添加以下依赖项:

Maven

1
2
3
4
5
6
7
8
9
<dependencies>
<!-- Gson: Java to JSON conversion -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
<scope>compile</scope>
</dependency>
</dependencies>

Gradle

1
2
3
dependencies {
implementation 'com.google.code.gson:gson:2.10.1'
}

gson 版本根据实际情况进行选择,建议使用最新版本(见 Maven Central )。

本文使用的是 2.10.1 版本(当前最新版本)。

数组的序列化与反序列化

对于数组,Gson 提供了简单而方便的序列化和反序列化方法。下面是一个示例:

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
package com.johnson.gson;

import com.google.gson.Gson;

/**
* @author johnson lin
* @date 2023/8/1 00:05
*/
public class ArraySerializationExample {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};

// 序列化
Gson gson = new Gson();
String json = gson.toJson(numbers);
System.out.println(json); // 输出:[1,2,3,4,5]

// 反序列化
int[] deserializedNumbers = gson.fromJson(json, int[].class);
for (int number : deserializedNumbers) {
System.out.print(number + " "); // 输出:1 2 3 4 5
}
}
}

/*
此代码示例执行结果如下:

[1,2,3,4,5]
1 2 3 4 5

*/

Gson 还支持具有任意复杂元素类型的多维数组,如对二维整型数组进行序列化与反序列化:

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
package com.johnson.gson;

import com.google.gson.Gson;

/**
* @author johnson lin
* @date 2023/8/1 00:43
*/
public class MultiDimensionalArrayExample {
public static void main(String[] args) {
int[][] numbers = {
{1, 2, 3},
{8, 9, 0}
};

// 序列化
Gson gson = new Gson();
String json = gson.toJson(numbers);
System.out.println(json); // 输出:[[1,2,3],[8,9,0]]

// 反序列化
int[][] deserializedNumbers = gson.fromJson(json, int[][].class);
for (int[] number : deserializedNumbers) {
for(int i : number) {
System.out.print(i + " "); // 输出:1 2 3 8 9 0
}
}
}
}
/*
此代码示例执行结果如下:

[[1,2,3],[8,9,0]]
1 2 3 8 9 0

*/

集合的序列化与反序列化

对于集合,Gson 同样提供了便捷的方法。以下是一个示例:

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
package com.johnson.gson;

import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.List;

/**
* @author johnson lin
* @date 2023/8/1 00:08
*/
public class CollectionSerializationExample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Johnson");
names.add("Charlie");

// 序列化
Gson gson = new Gson();
String json = gson.toJson(names);
System.out.println(json); // 输出:["Alice","Bob","Johnson","Charlie"]

// 反序列化
List<String> deserializedNames = gson.fromJson(json, List.class);
for (String name : deserializedNames) {
System.out.print(name + " "); // 输出:Alice Bob Johnson Charlie
}
}
}
/*
此代码示例执行结果如下:

["Alice","Bob","Johnson","Charlie"]
Alice Bob Johnson Charlie

*/

集合限制:Gson 可以将任意类型的对象集合进行序列化,但无法从中进行反序列化,因为用户无法指出生成对象的类型。相反,在反序列化时,集合必须是特定的通用类型。这是有道理的,只要遵循良好的 Java 编码实践,就很少会出现问题。

映射的序列化与反序列化

默认情况下,Gson 将任何 java.util.Map 实现(如 HashMapLinkedHashMap 等)序列化为 JSON 对象。由于 JSON 对象仅支持字符串作为成员名称,因此 Gson 通过调用 toString() 将 Map 键转换为字符串,并对 null 键使用 "null"

对于反序列化,Gson 使用注册为 Map 键类型的 TypeAdapterread 方法。为了进行反序列化,必须使用 TypeToken 来告诉 Gson Map 键和值的类型是什么。

下面是一个对包含 null 键的 Map 进行序列化与反序列化的示例:

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.johnson.gson;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.util.LinkedHashMap;
import java.util.Map;

/**
* @author johnson lin
* @date 2023/8/1 01:37
*/
public class MapSerializationExample02 {
public static void main(String[] args) {
Gson gson = new Gson();

Map<String, String> stringMap = new LinkedHashMap<>();
stringMap.put("key", "value");
stringMap.put(null, "null-entry");

Map<Integer, Integer> intMap = new LinkedHashMap<>();
intMap.put(1, 1);
intMap.put(3, 3);

// 序列化
String json1 = gson.toJson(stringMap);
System.out.println(json1); // 输出:{"key":"value","null":"null-entry"}

String json2 = gson.toJson(intMap);
System.out.println(json2); // 输出:{"1":1,"3":3}

System.out.println();

// 反序列化
TypeToken<Map<String, String>> strMapType = new TypeToken<Map<String, String>>(){};
Map<String, String> deserializedString = gson.fromJson(json1, strMapType);

for (Map.Entry<String, String> entry : deserializedString.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 输出:
// key: value
// null: null-entry
System.out.println();

TypeToken<Map<Integer, Integer>> intMapType = new TypeToken<Map<Integer, Integer>>(){};
Map<Integer, Integer> deserializedInteger = gson.fromJson(json2, intMapType);
for (Map.Entry<Integer, Integer> entry : deserializedInteger.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 输出:
// 1: 1
// 3: 3
}
}
/*
此代码示例执行结果如下:

{"key":"value","null":"null-entry"}
{"1":1,"3":3}

key: value
null: null-entry

1: 1
3: 3

*/

请注意:上述示例代码中,在反序列化时我们是如何定义映射类型的。代码看起来相当丑陋,但遗憾的是,在 Java 中无法绕过这一点。

下面是一个利用 Gson 将 Map<String, Integer> 转换成 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
40
41
42
43
44
45
46
47
package com.johnson.gson;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.util.HashMap;
import java.util.Map;

/**
* @author johnson lin
* @date 2023/8/1 00:10
*/
public class MapSerializationExample {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 90);
scores.put("Bob", 80);
scores.put("Johnson", 99);
scores.put("Charlie", 95);

// 序列化
Gson gson = new Gson();
String json = gson.toJson(scores);
System.out.println(json); // 输出:{"Johnson":99,"Bob":80,"Alice":90,"Charlie":95}

// 反序列化
Map<String, Integer> deserializedScores = gson.fromJson(json, new TypeToken<Map<String, Integer>>(){});
for (Map.Entry<String, Integer> entry : deserializedScores.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 输出:
// Johnson: 99
// Bob: 80
// Alice: 90
// Charlie: 95
}
}
/*
此代码示例执行结果如下:

{"Johnson":99,"Bob":80,"Alice":90,"Charlie":95}
Johnson: 99
Bob: 80
Alice: 90
Charlie: 95

*/

小结

本文介绍了如何使用 Gson 库对数组、集合和映射进行序列化和反序列化操作。通过 Gson 提供的简单而强大的 API,我们可以轻松地将这些常见的数据结构转换为 JSON 字符串,并且能够方便地将 JSON 字符串还原成原始的数据结构。使用 Gson 库,我们可以更加高效地处理和传输数据,为我们处理复杂的数据结构提供了很大的灵活性和便利性,在 Java 开发中起到了很大的作用。

(END)