昨天下午 5 点 10 分左右,我解决掉了最后一个 bug,轻舒一口气,准备关机下班。可这个时候,老板朝我走来,脸上挂着神秘的微笑,我就知道他不怀好意。果不其然,他扔给了我一个新的需求,要我在 Java 中解析 JSON,并且要在半个小时候给出最佳的解决方案。
无奈,提前下班的希望破灭了。不过,按时下班的希望还是有的。于是我撸起袖子开始了研究,结果出乎我的意料,竟然不到 10 分钟就找出了最佳方案。但我假装还没有搞出来,趁着下班前的这段时间把方案整理成了现在你们看到的这篇文章。
01、JSON 是什么
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,机器解析和生成起来更是轻而易举。JSON 采用了完全独立于编程语言的文本格式,但它的格式非常符合 C 语言家族的习惯(比如 C、C++、C#、Java、JavaScript、Python 等)。 这种特质使得 JSON 成为了最理想的数据交换格式。
JSON 建构于两种常见的数据结构:
“键/值”对。
数组。
这使得 JSON 在同样基于这些结构的编程语言之间的交换成为可能。在 Java 中,解析 JSON 的第三方类库有很多,比如说下面这些。
很多,对不对?但日常开发中,最常用的只有四个:Gson、Jackson、org.json 和阿里巴巴的 fastjson。下面我们来简单地对比下。
02、Gson
Gson 是谷歌提供的一个开源库,可以将 Java 对象序列化为 JSON 字符串,同样可以将 JSON 字符串反序列化(解析)为匹配的 Java 对象。
使用 Gson 之前,需要先在项目中引入 Gson 的依赖。
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.6</version> <scope>compile</scope> </dependency>
1)简单示例
Gson gson = new Gson(); gson.toJson(18); // ==> 18 gson.toJson("沉默王二"); // ==> "沉默王二"
上面这段代码通过 new 关键字创建了一个 Gson 对象,然后调用其 toJson() 方法将整形和字符串转成了 JSON 字符串。
同样,可以调用 fromJson() 方法将简单的 JSON 字符串解析为整形和字符串。
int one = gson.fromJson("18", int.class);
Integer one1 = gson.fromJson("18", Integer.class);
String str = gson.fromJson("\"沉默王二\"", String.class);
2)复杂点的示例
Cmower 类有两个字段:整形 age 和 字符串 name。
class Cmower { private int age = 18; private String name = "沉默王二"; }
将其转成 JSON 字符串。
Gson gson = new Gson(); String json = gson.toJson(new Cmower()); System.out.println(json);
输出结果为:
{"age":18,"name":"沉默王二"}
1
可以再通过 fromJson() 方法将字符串 json 解析为 Java 对象。
gson.fromJson(json, Cmower.class);
1
3)数组示例
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"沉", "默", "王二"};
// 转成 JSON 字符串
gson.toJson(ints); // ==> [1,2,3,4,5]
gson.toJson(strings); // ==> ["沉", "默", "王二"]
// 解析为数组
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
String[] strings2 = gson.fromJson("[\"沉\", \"默\", \"王二\"]", String[].class);
数组的处理仍然非常简单,调用的方法也仍然是 toJson() 和 fromJson() 方法。
4)集合示例
Gson gson = new Gson();
List<String> list = new ArrayList<>(Arrays.asList("沉", "默", "王二"));
String json = gson.toJson(list); // ==> ["沉","默","王二"]
把集合转成 JSON 字符串并没有什么特别之处,不过,把 JSON 字符串解析为集合就和之前的方法有些不同了。
Type collectionType = new TypeToken<ArrayList<String>>(){}.getType();
List<String> list2 = gson.fromJson(json, collectionType);
我们需要借助 com.google.gson.reflect.TypeToken 和 java.lang.reflect.Type 来获取集合的类型,再将其作为参数传递给 formJson() 方法,才能将 JSON 字符串解析为集合。
Gson 虽然可以将任意的 Java 对象转成 JSON 字符串,但将字符串解析为指定的集合类型时就需要花点心思了,因为涉及到了泛型——TypeToken 是解决这个问题的银弹。
关于 Gson,我们就先说到这吧,以后有机会的时候再和大家细说。