本文是gson系列文章的第一篇。本文是其他文章的基礎,是以不需要任何gson或json經驗。第二篇文章提供了關于gson反序列化(從json到java)的示例,第三篇文章提供了關于gson序列化(從java到json)的示例。
下載下傳與安裝
<dependency>
<groupid>com.google.code.gson</groupid>
<artifactid>gson</artifactid>
<version>2.2.4</version>
</dependency>
如果這個庫用于web應用,請確定在web-inf/lib檔案夾中保持一份拷貝。或者,gson庫可以放到應用伺服器提供給web應用。
一個簡單示例
package com.javacreed.examples.gson.part1;
import com.google.gson.gson;
import com.google.gson.gsonbuilder;
public class simpleexample1 {
public static void main(string[] args) {
gson gson = new gsonbuilder().create();
gson.tojson("hello", system.out);
gson.tojson(123, system.out);
}
}
在上面的例子中,我們建立了一個gson執行個體,并把java string和int轉化為json對象。以上代碼指令行裡的輸出結果如下:
"hello"123
這不是火箭科學,但它是一個開始。注意,上述的結果都将輸入到指令行。該tojason()方法有兩個參數,java對象轉換為json和可追加(java的文檔)的一個執行個體。我們可以很容易地改變了一個檔案或網絡流。
import java.io.filewriter;
import java.io.ioexception;
import java.io.writer;
public class simpleexample2 {
public static void main(string[] args) throws ioexception {
writer writer = new filewriter("output.json");
gson.tojson("hello", writer);
gson.tojson(123, writer);
writer.close();
注意
為什麼變量聲明為writer類型,而實際類型是filewriter?
盡量使用泛型是一個很好的方法。在上例中,我們隻使用了appendable和writer接口定義的方法。使用泛型使代碼更易于移植和維護,下面是個不好的例子。
public static void main(string[] args) throws ioexception {
try (writer writer = new filewriter("output.json")) {
以上代碼生成檔案:包含json對象的output.json。注意,這裡我們使用了字元流而不是位元組流。因為tojson()方法需要一個
appendanble執行個體,而位元組流不能實作appendable接口,是以我們使用了字元流。appendable接口處理字元而不是位元組。java
注意,使用inputstreamreader和outputstreamwriter類時,如果不提供編碼或者字元集,轉換将使用平台預設字元集。這将降低代碼的可移植性,且在其他平台上運作将可能産生錯誤行為。
import java.io.fileoutputstream;
import java.io.outputstreamwriter;
public class simpleexample3 {
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命名規範,暫時隻是為了簡化。更
package 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檔案夾的檔案裡(這不是正常做法)。
import java.io.inputstreamreader;
import java.io.reader;
public class jsontojava {
try(reader reader = new inputstreamreader(jsontojava.class.getresourceasstream("/server1.json"), "utf-8")){
person p = gson.fromjson(reader, person.class);
system.out.println(p);
輸出如下:
albert attard - malta
gson解析json對象并建立了一個person類的執行個體,并列印到指令行中。
嵌套json對象
讓我們對上面的例子更進一步,以下所示json代碼段包含了一個嵌套對象。
location:"malta",
exam: {
subject:"programming",
grade:4.5
}
exam域由兩個域組成,分别是<code>subject和</code><code>grade。我們需要修改person類的定義來包含exam域,并建立一個新的java類來表示exam,該類包含subject和grade域。</code>
我們首先建立新的類來表示嵌套對象。就像之前讨論那樣,類名無關緊要,但是域名必須與json中的域名比對。
package com.javacreed.examples.gson.part3;
public class exam {
private string subject;
private double grade;
return subject + " - " + grade;
現在我們可以修改person類,引入一個與json中exam同名的域,類型為exam。注意,下面的person類與前一個<span style=”color: #ff0000;”>位于</span>不同的包。
private exam exam;
return name + " - " + location + " (" + exam + ")";
最後,讓我們嘗試新的變化。
try(reader reader = new inputstreamreader(jsontojava.class.getresourceasstream("/server2.json"), "utf-8")){
jsontojava類沒有做任何改變,因為gson使用了模型(person和exam類)将json映射成java。
結論
即使json可能是一個新概念,但它十分簡單與直接。此外,相比于需要增加标簽進行消息/資料轉換而不斷膨脹的笨重的xml,它因為簡單更加流行。
需要指出json是javascript的一個子集,javascript将它作為一個完美的方案來進行資料交換,例如網頁。gson
api使它更便于使用,即使在這裡沒有讨論的部分,它也提供了強大的靈活性。
來源:51cto