首页 前端知识 Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器,强烈推荐

Gson:GitHub 标星 18K 的 JSON 解析器,Google 出品的 Java JSON 解析器,强烈推荐

2024-05-08 10:05:55 前端知识 前端哥 681 508 我要收藏

2)不需要使用任何的注解来表明哪些字段需要序列化,哪些字段不需要序列化。默认情况下,包括所有的字段,以及从父类继承过来的字段。

3)如果一个字段被 transient 关键字修饰的话,它将不参与序列化。

4)如果一个字段的值为 null,它不会在序列化后的结果中显示。

5)JSON 中缺少的字段将在反序列化后设置为默认值,引用数据类型的默认值为 null,数字类型的默认值为 0,布尔值默认为 false。

接下来,来看一个序列化集合的例子。

List list =new ArrayList<>();

list.add(“好好学习”);

list.add(“天天向上”);

String json = gson.toJson(list);

结果如下所示:

[“好好学习”,“天天向上”]

反序列化的时候,也很简单。

List listResult = gson.fromJson(json,List.class);

结果如下所示:

[好好学习, 天天向上]

我女朋友是一个很细心也很贴心的人,在你调用 toJson() 方法进行序列化的时候,她会先判 null,防止抛出 NPE,再通过 getClass() 获取参数的类型,然后进行序列化。

public String toJson(Object src) {

if (src == null) {

return toJson(JsonNull.INSTANCE);

}

return toJson(src, src.getClass());

}

但是呢?对于泛型来说,getClass() 的时候会丢掉参数化类型。来看下面这个例子。

public class Foo {

T value;

public void set(T value) {

this.value = value;

}

public T get() {

return value;

}

public static void main(String[] args) {

Gson gson = new Gson();

Foo foo = new Foo();

Bar bar = new Bar();

foo.set(bar);

String json = gson.toJson(foo);

}

}

class Bar{

private int age = 10;

private String name = “图灵”;

}

假如你 debug 的时候,进入到 toJson() 方法的内部,就可以观察到。

foo 的实际类型为 Foo<Bar>,但我女朋友在调用 foo.getClass() 的时候,只会得到 Foo,这就意味着她并不知道 foo 的实际类型。

序列化的时候还好,反序列化的时候就无能为力了。

Foo foo1 = gson.fromJson(json, foo.getClass());

Bar bar1 = foo1.get();

这段代码在运行的时候就报错了。

Exception in thread “main” java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap cannot be cast to class com.itwanger.gson.Bar (com.google.gson.internal.LinkedTreeMap and com.itwanger.gson.Bar are in unnamed module of loader ‘app’)

at com.itwanger.gson.Foo.main(Foo.java:36)

默认情况下,泛型的参数类型会被转成 LinkedTreeMap,这显然并不是我们预期的 Bar,女朋友对此表示很无奈。

作为 Google 的亲儿子,我的血液里流淌着“贵族”二字,我又怎能忍心女朋友无助时的落寞。

于是,我在女朋友的体内植入了另外两种方法,带 Type 类型参数的:

toJson(Object src, Type typeOfSrc);

T fromJson(String json, Type typeOfT);

这样的话,你在进行泛型的序列化和反序列化时,就可以指定泛型的参数化类型了。

Type fooType = new TypeToken<Foo>() {}.getType();

String json = gson.toJson(foo,fooType);

Foo foo1 = gson.fromJson(json, fooType);

Bar bar1 = foo1.get();

debug 进入 toJson() 方法内部查看的话,就可以看到 foo 的真实类型了。

fromJson() 在反序列化的时候,和此类似。

这样的话,bar1 就可以通过 foo1.get() 到了。

瞧,我考虑得多周全,女朋友都忍不住夸我了!

05、处理混合类型

你知道的,Java 不建议使用混合类型,也就是下面这种情况。

List list = new ArrayList();

list.add(“沉默王二”);

list.add(18);

list.add(new Event(“gson”, “google”));

Event 的定义如下所示:

class Event {

private String name;

private String source;

Event(String name, String source) {

this.name = name;

this.source = source;

}

}

由于 list 没有指定具体的类型,因此它里面可以存放各种类型的数据。这样虽然省事,我女朋友在序列化的时候也没问题,但反序列化的时候就要麻烦多了。

Gson gson = new Gson();

String json = gson.toJson(list);

System.out.println(json);

输出结果如下所示:

[“沉默王二”,18,{“name”:“gson”,“source”:“google”}]

反序列化的时候,就需要花点心思才能拿到 Event 对象。

JsonParser parser = new JsonParser();

JsonArray array = parser.parse(json).getAsJsonArray();

String message = gson.fromJson(array.get(0), String.class);

int number = gson.fromJson(array.get(1), int.class);

Event event = gson.fromJson(array.get(2), Event.class);

承认了,JsonParser 是我的前任。希望你不要喷我渣男,真不是我花心,是因为我们性格上有些不太适合。但我们仍然保持着朋友的关系,因为我们谁都没有错,只是代码更加规范了,已经很少有开发者使用混合类型了。

06、个性化定制

考虑到你是一个追求时髦的人,我一直对自己要求很高,力争能够满足你的所有需求。这种高标准的要求,让我女朋友对我是又爱又恨。

爱的是,我这种追求完美的态度;恨的是,她有时候力不从心,帮不上忙。

使用 toJson() 序列化 Java 对象时,返回的 JSON 字符串中没有空格,很紧凑。如果你想要打印更漂亮的 JSON 格式,你需要打电话给一个叫 GsonBuilder 的老板,让他进行一些定制,然后再把复刻版邮寄给你,就像我在使用指南中提到的那样。

public class Writer {

private int age = 18;

private String name = “沉默王二”;

public static void main(String[] args) {

Writer writer = new Writer();

Gson gson = new Gson();

String json = gson.toJson(writer);

System.out.println(json);

Gson gson1 = new GsonBuilder().setPrettyPrinting().create();

String jsonOutput = gson1.toJson(writer);

System.out.println(jsonOutput);

}

}

来对比一下输出结果:

{“age”:18,“name”:“沉默王二”}

{

“age”: 18,

“name”: “沉默王二”

}

通过 setPrettyPrinting() 定制后,输出的格式更加层次化、立体化,字段与值之间有空格,每个不同的字段之间也会有换行。

之前提到了,默认情况下,我女朋友在序列化的时候会忽略 null 值的字段,如果不想这样的话,同样可以打电话给 GsonBuilder。

public class Writer {

private int age = 18;

private String name = null;

public static void main(String[] args) {

Writer writer = new Writer();

Gson gson = new Gson();

String json = gson.toJson(writer);

System.out.println(json);

Gson gson2 = new GsonBuilder().serializeNulls().create();

String jsonOutput2 = gson2.toJson(writer);

System.out.println(jsonOutput2);

}

}

来对比一下输出结果:

{“age”:18}

{“age”:18,“name”:null}

通过 serializeNulls() 定制后,序列化的时候就不会再忽略 null 值的字段。

也许,你在序列化和反序列化的时候想要筛选一些字段,我也考虑到这种需求了,特意为你准备了几种方案,你可以根据自己的口味挑选适合你的。

第一种,通过 Java 修饰符

你之前也看到了,使用 transient 关键字修饰的字段将不会参与序列化和反序列化。同样的,static 关键字修饰的字段也不会。如果你想保留这些关键字修饰的字段,可以这样做。

保留单种。

Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.TRANSIENT).create();

保留多种。

Gson gson = new GsonBuilder()

.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)

.create();

第二种,通过 @Expose 注解

要使用 @Expose 注解,你需要先这样做:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后希望可以帮助到大家!

千千万万要记得:多刷题!!多刷题!!

之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!

篇幅有限,以下只能截图分享部分的资源!!

(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)

image

(2)刷的算法题(还有左神的算法笔记)

image

(3)面经+真题解析+对应的相关笔记(很全面)

image

(4)视频学习(部分)

ps:当你觉得学不进或者累了的时候,视频是个不错的选择

在这里,最后只一句话:祝大家offer拿到手软!!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

添加V获取:vip1024b (备注Java)**
[外链图片转存中…(img-WZh4fg43-1712788110410)]

最后希望可以帮助到大家!

千千万万要记得:多刷题!!多刷题!!

之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!

篇幅有限,以下只能截图分享部分的资源!!

(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)

[外链图片转存中…(img-td4yjGOd-1712788110410)]

(2)刷的算法题(还有左神的算法笔记)

[外链图片转存中…(img-nR45HNqi-1712788110411)]

(3)面经+真题解析+对应的相关笔记(很全面)

[外链图片转存中…(img-9gocSADu-1712788110411)]

(4)视频学习(部分)

ps:当你觉得学不进或者累了的时候,视频是个不错的选择

在这里,最后只一句话:祝大家offer拿到手软!!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-TTFruRzJ-1712788110411)]

转载请注明出处或者链接地址:https://www.qianduange.cn//article/7484.html
标签
github
评论
发布的文章

JQuery中的load()、$

2024-05-10 08:05:15

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!