java gson序列化_Java 中使用 Gson 反序列化 JSON 数据

好长时间没写 Java,发现序列化、反序列化一个 JSON 数据真不是个容易的事情(主要还是年纪大了,记不住)。于是记录一下使用 Gson 反序列化的方法。文中涉及的代码都可以在这个 gson-deserialization-example 中找到。

作者本身不懂 Java,本着不负责的态度写下这些内容,大牛勿喷,想抄代码的菜鸟请珍重。

本文基于转换期间没有异常情况讨论,实际情况请珍重。

初始化

我们先创建一个简单的 TestMain.java 文件,用来运行我们后续的测试方法。

TestMain.java1

2

3

4

5public class TestMain{

public static void main(String args[]){

// 运行测试方法

}

}

通过 javac TestMain.java 会生成 TestMain.class 文件,之后就能通过 java TestMain 运行 class 文件。

在当前的例子中我们 google 的 Gson( maven 地址) 库来做序列化和反序列化。简单起见,我们直接下载 jar 包,放到 lib 目录下。

因为我们使用了 gson.jar 所以命令会变成这样:

javac -classpath lib/gson-2.8.0.jar TestMain.java

java -classpath .:lib/gson-2.8.0.jar TestMain

JsonParser

Object

假设我们有这样一个简单的 JSON 数据:

1

2

3

4

5

6

7

8

9

10

11

12/* Sample JSON */

{

"name": "Hans Chan",

"age": 18,

"tags": [{

"id": 1,

"text": "JavaScript"

}, {

"id": 2,

"text": "Java"

}]

}

使用 JsonParser 足够的简单:

1

2JsonParser jsonParser = new JsonParser();

JsonElement userJsonElement = jsonParser.parse(json);

所有东西都是 抽象 的 JsonElement(api),如果要获取具体的内容,就得转换成 JsonObject 或 JsonArray 等类型,获取方式也非常直观 .get("key"):

1

2

3

4JsonObject userJsonObject = userJsonElement.getAsJsonObject();

String name = userJsonObject.get("name").getAsString();

int age = userJsonObject.get("age").getAsInt();

JsonArray userTagsJsonArray = userJsonObject.get("tags").getAsJsonArray();

Array

同样的场景,如果输入的 json 字符串不是 {} 而是 [],也可以通过上述方法获取:

1

2

3

4

5

6String json = "[{},{}]"; // 每个 {} 都是一个 Sample JSON

JsonArray userJsonArray = jsonParser.parse(json).getAsJsonArray(); // 不是 getAsJsonObject

for (int i = 0; i < userJsonArray.size(); i++) {

JsonObject userJsonObject = userJsonArray.get(i).getAsJsonObject();

// ...

}

Serialization

JsonElement 的序列化很简单,直接 .toString() 即可。

1String json = userJsonObject.toString(); // JsonObject

OO

这下子,写 Java 的哥们就肯定会跳出来说 “这是什么鬼,一点都不 OO”。的确上面的方式很 js,于是我们就要写得像 Java 一点,先来两个 class :

1

2

3

4

5

6

7

8

9

10

11private class Tag{

private int id;

private String text;

// 此处省略 Getter and Setter

}

private class User{

private String name;

private int age;

private List tags;

// 此处省略 Getter and Setter

}

Object

大家注意了,我要变形了!(敲黑板)

1

2Gson gson = new Gson();

User user = gson.fromJson(json, User.class);

通过 Gson,String 被转换成指定的 User.class,然后我们就可以愉快地操作这个实例了:

1

2

3

4

5List tags = user.getTags();

for (int i = 0; i < tags.size(); i++) {

Tag tag = tags.get(i);

System.out.println("tag " + tag.getId() + ": " + tag.getText());

}

Array

还是同样的例子,如果是 [] 怎么办?我们当然期望是获得一个 List 啦,但没有 List.class 这个东西,怎么破?没关系,Gson 里面还有个 TypeToken 是可以跟你干这事的,我们只需要这样:

1

2

3

4

5

6// import com.google.common.reflect.TypeToken;

TypeToken typeToken = new TypeToken>() {};

// import java.lang.reflect.Type;

Type type = typeToken.getType();

List users = gson.fromJson(json, type);

还是可以愉快地玩耍的,不是麽 😂

Serialization

Class 要反序列化就还是要依赖回 Gson 提供的 toJson 方法:

1String json = gson.toJson(user); // User

GsonBuilder

很多时候,输入的 json 总有那么一点不尽人意,例如下面这个例子:

1

2

3

4

5

6

7

8

9

10

11

12{

"id": 3,

"name": "Hans Chan",

"registrationTime": "1999-09-19 18:10:22",

"data": {

"some": "complex data",

"we": {

"do-NOT": ["care", "about", "what", "inside"],

"BUT": "needed!"

}

}

}

id 是我们需要的数据,但序列化出去的时候不想显示

registrationTime 可能不是一个我们想要的格式

data 可能是我们不是很关心结构,但又需要保存里面的内容

利用 GsonBuilder 和 Annotation 我们就可以实现上面两个功能:

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

28private class BaseUser{

// import com.google.gson.annotations.Expose;

@Expose(serialize = false, deserialize = true)

private int id;

@Expose

private String name;

// import com.google.gson.annotations.SerializedName;

@SerializedName("registrationTime")

@Expose

private Date registration;

public int getId(){

return id;

}

public Date getRegistration(){

return registration;

}

}

private class CustomBUser extends BaseUser{

@Expose

private JsonElement data;

public JsonElement getData(){

return data;

}

}

registrationTime 的格式我们用 GsonBuilder 声明:

1

2

3

4

5

6Gson deserializationGson = new GsonBuilder()

// 不导出实体中没有用 @Expose 注解的属性

.excludeFieldsWithoutExposeAnnotation()

// 时间格式

.setDateFormat("yyyy-MM-dd HH:mm:ss")

.create();

愉快地玩耍吧:

1

2

3CustomBUser cbu = deserializationGson.fromJson(json, CustomBUser.class);

System.out.println("id: " + cbu.getId());

System.out.println(cau.getData());

自定义序列化和反序列化

上面的例子中,data 是直接用一个 JsonElement 来处理的,如果有更加个性化的要求,那就需要自己写序列化和反序列化方法了。这里我们自己实现一个 CustomUserData 类,用来处理 data 数据,直接实现上面相同的功能:

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

34private static class CustomUserData{

private JsonElement ctx;

public CustomUserData(JsonElement ctx){

this.ctx = ctx;

}

public String toString(){

return this.ctx.toString();

}

}

private class CustomAUser extends BaseUser{

@Expose

private CustomUserData data;

public CustomUserData getData(){

return data;

}

}

// 自定义反序列化方法

private static class CustomUserDataDeserializeAdapter implements JsonDeserializer{

@Override

public CustomUserData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)

throws JsonParseException{

// 这里实现复杂的功能

return new CustomUserData(json);

}

}

// 自定义序列化方法

public static class CustomUserDataSerializeAdapter implements JsonSerializer{

@Override

public JsonElement serialize(CustomUserData src, Type typeOfSrc, JsonSerializationContext context){

// 这里实现复杂的功能

return src.ctx;

}

}

通过 registerTypeAdapter 给 GsonBuilder 注册上面的自定义序列化方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18Gson deserializationGson = new GsonBuilder()

.excludeFieldsWithoutExposeAnnotation()

.setDateFormat("yyyy-MM-dd HH:mm:ss")

.registerTypeAdapter(CustomUserData.class, new CustomUserDataDeserializeAdapter())

.create();

Gson serializationGson = new GsonBuilder()

.excludeFieldsWithoutExposeAnnotation()

.setDateFormat("yyyy/MM/dd HH:mm:ss")

.registerTypeAdapter(CustomUserData.class, new CustomUserDataSerializeAdapter())

.setPrettyPrinting()

.create();

System.out.println("---------- CustomAUser ----------");

CustomAUser cau = deserializationGson.fromJson(json, CustomAUser.class);

System.out.println("id: " + cau.getId());

// System.out.println(cau.getRegistration());

// System.out.println(cau.getData()); // .toString()

System.out.println(serializationGson.toJson(cau));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值