Gson 用户指南
gson.toJson(123, writer);
}
}
以上代码生成文件:包含 JSON 对象的 Output.json。注意,这里我们使用了字符流而不是字节流。因为 toJson()方法需要一个 Appendanble 实例,而字节流不能实现 Appendable 接口,所以我们使用了字符流。Appendable 接口处理字符而不是字节。Java 提供了 InputStreanReader(Java 文档)和 OutputStreamWriter(Java 文档)类进行字节流与字符流的转换,如下面的例子。
注意
注意,使用 InputStreamREader 和 OutputStreamWriter 类时,如果不提供编码或者字符集,转换将使用平台默认字符集。这将降低代码的可移植性,且在其他平台上运行将可能产生错误行为。
package com.javacreed.examples.gson.part1;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class SimpleExample3 {
public static void main(String[] args) throws IOException {
try(Writer writer = new OutputStreamWriter(new FileOutputStream("Output.json") , "UTF-8")){
Gson gson = new GsonBuilder().create();
gson.toJson("Hello", writer);
gson.toJson(123, writer);
}
}
}
如你所见,我们只需要改变实例的一部分。代码的剩余部分没有任何变化。这就是使用接口代替类作为变量类型的好处之一。
使用 JSON 对象
比方说,我们需要使用 JSON 对象并加载他们为 Java 对象。假设 web 服务器查询时产生如下 JSON 对象:
{
NAME:"Albert Attard",
P_LANGUAGE:"Java",
LOCATION:"Malta"
}
此 JSON 对象包含 3 个不同值的域。比如我们需要使用 JSON 对象并创建一个 Java 对象来展示它。为了使这个例子更有趣,假设我们只关心 name 和 location 域。
首先创建一个 Java 类来表示 name 和 location。类命名为 Person。类的名字无关紧要,但域的名字必须一致。域名必须匹配(大小写敏感)JSON 对象中的名字。更进一步,类必须包含一个默认构造函数(即使它被设置为 private)。如下所示,name 和 location 域在 JSON 中是大写的。JSON 中域 P_LANGUAGE 被忽略了,因为 Java 对象中不包括该名称的域。请理解域名不遵守 Java 命名规范,暂时只是为了简化。更多内容将在第 2 部分中讨论。
p
ackage com.javacreed.examples.gson.part2;
public class Person {
private String NAME;
private String LOCATION;
// Getters and setters are not required for this example.
// GSON sets the fields directly using reflection.
@Override
public String toString() {
return NAME + " - " + LOCATION;
}
}
准备好 Java 对象后,我们可以读取 JSON 对象并加载为 Java 对象,如下代码所示。为了模拟真实情况,我们使用了字节流作为输入。还要注意,JSON 内容保存在 resource 文件夹的文件里(这不是常规做法)。
package com.javacreed.examples.gson.part2;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class JsonToJava {
public static void main(String[] args) throws IOException {
try(Reader reader = new InputStreamReader(JsonToJava.class.getResourceAsStream("/Server1.json"), "UTF-8")){
Gson gson = new GsonBuilder().create();
Person p = gson.fromJson(reader, Person.class);
System.out.println(p);
}
}
}
输出如下:
Albert Attard - Malta
Gson 解析 JSON 对象并创建了一个 Person 类的实例,并打印到命令行中。
嵌套 JSON 对象
让我们对上面的例子更进一步,以下所示 JSON 代码段包含了一个嵌套对象。
{
NAME:"Albert Attard",
P_LANGUAGE:"Java",
LOCATION:"Malta",
EXAM: {
SUBJECT:"Programming",
GRADE:4.5
}
}
EXAM 域由两个域组成,分别是 SUBJECT 和 GRAD
E。我们需要修改 Person 类的定义来包含 EXAM 域,并创建一个新的 Java 类来表示 EXAM,该类包含 SUBJECT 和 GRADE 域。
我们首先创建新的类来表示嵌套对象。就像之前讨论那样,类名无关紧要,但是域名必须与 JSON 中的域名匹配。
package com.javacreed.examples.gson.part3;
public class Exam {
private String SUBJECT;
private double GRADE;
// Getters and setters are not required for this example.
// GSON sets the fields directly using reflection.
@Override
public String toString() {
return SUBJECT + " - " + GRADE;
}
}
现在我们可以修改 Person 类,引入一个与 JSON 中 EXAM 同名的域,类型为 Exam。注意,下面的 Person 类与前一个
package com.javacreed.examples.gson.part3;
public class Person {
private String NAME;
private String LOCATION;
private Exam EXAM;
@Override
public String toString() {
return NAME + " - " + LOCATION + " (" + EXAM + ")";
}
}
注意,所需的变化是最小的,因为 Gson 动态发现(使用反射)类和它的域。本文不包含反射,对于更多关于反射的信息,请参考:Reflection in Action.
最后,让我们尝试新的变化。
package com.javacreed.examples.gson.part3;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class JsonToJava {
public static void main(String[] args) throws IOException {
try(Reader reader = new InputStreamReader(JsonToJava.class.getResourceAsStream("/Server2.json"), "UTF-8")){
Gson gson = new GsonBuilder().create();
Person p = gson.fromJson(reader, Person.class);
System.out.println(p);
}
}
}
JsonToJava 类没有做任何改变,因为 Gson 使用了模型(Person 和 Exam 类)将 Json 映射成 Java。作者:阙沂平
评论