1. 概述
本教程將教您如何使用 Gson 序列化和反序列化基本數據類型。Google 開發了 Gson 庫用於序列化和反序列化 JSON。此外,我們還將學習 Gson 庫在處理基本數據類型時的一些特定特性。
另一方面,如果我們需要處理數組、集合、嵌套對象或其他自定義內容,我們有關於使用 Gson 進行序列化和使用 Gson 進行反序列化的附加教程。
2. Maven 依賴
為了使用 Gson,我們需要將 Gson 依賴添加到 pom 中:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>3. 原始類型序列化
使用 Gson 進行序列化非常簡單。我們將使用以下模型作為示例:
public class PrimitiveBundle {
public byte byteValue;
public short shortValue;
public int intValue;
public long longValue;
public float floatValue;
public double doubleValue;
public boolean booleanValue;
public char charValue;
}首先,讓我們用一些測試值初始化一個實例:
PrimitiveBundle primitiveBundle = new PrimitiveBundle();
primitiveBundle.byteValue = (byte) 0x00001111;
primitiveBundle.shortValue = (short) 3;
primitiveBundle.intValue = 3;
primitiveBundle.longValue = 3;
primitiveBundle.floatValue = 3.5f;
primitiveBundle.doubleValue = 3.5;
primitiveBundle.booleanValue = true;
primitiveBundle.charValue = 'a';接下來,我們可以對其進行序列化:
Gson gson = new Gson();
String json = gson.toJson(primitiveBundle);最後,我們可以看到序列化後的結果:
{
"byteValue":17,
"shortValue":3,
"intValue":3,
"longValue":3,
"floatValue":3.5,
"doubleValue":3.5,
"booleanValue":true,
"charValue":"a"
}我們應該注意一些細節,從我們的示例來看。首先,字節值不作為位字符串序列化,就像在模型中那樣。此外,short、int 和 long 之間沒有區別。 另外,float 和 double 之間也沒有區別。
另一件需要注意的事是,字符串代表字符值。
實際上,這三個方面與 Gson 無關,但這是 JSON 的定義方式。
3.1. 序列化特殊浮點值
Java 提供了常量 Float.POSITIVE_INFINITY 和 NEGATIVE_INFINITY 用於表示無窮大。Gson 無法序列化這些特殊值:
public class InfinityValuesExample {
public float negativeInfinity;
public float positiveInfinity;
}InfinityValuesExample model = new InfinityValuesExample();
model.negativeInfinity = Float.NEGATIVE_INFINITY;
model.positiveInfinity = Float.POSITIVE_INFINITY;
Gson gson = new Gson();
gson.toJson(model);嘗試這樣做會引發一個 IllegalArgumentException。
嘗試序列化 NaN 也會引發一個 IllegalArgumentException,因為該值不符合 JSON 規範。
出於相同原因,嘗試序列化 Double.POSITIVE_INFINITY、NEGATIVE_INFINITY 或 NaN 也會拋出 IllegalArgumentException。
4. 原始類型反序列化
讓我們現在看看如何反序列化上一個示例中獲得的 JSON 字符串。
反序列化就像序列化一樣簡單:
Gson gson = new Gson();
PrimitiveBundle model = gson.fromJson(json, PrimitiveBundle.class);最後,我們可以驗證模型包含所需的值:
assertEquals(17, model.byteValue);
assertEquals(3, model.shortValue);
assertEquals(3, model.intValue);
assertEquals(3, model.longValue);
assertEquals(3.5, model.floatValue, 0.0001);
assertEquals(3.5, model.doubleValue, 0.0001);
assertTrue(model.booleanValue);
assertEquals('a', model.charValue);
4.1. 反序列化字符串值
當一個有效的字符串值被放置在一個 String 中,Gson 會解析它並以預期的方式處理它:
String json = "{\"byteValue\": \"15\", \"shortValue\": \"15\", "
+ "\"intValue\": \"15\", \"longValue\": \"15\", \"floatValue\": \"15.0\""
+ ", \"doubleValue\": \"15.0\"}";
Gson gson = new Gson();
PrimitiveBundleInitialized model = gson.fromJson(json, PrimitiveBundleInitialized.class);
assertEquals(15, model.byteValue);
assertEquals(15, model.shortValue);
assertEquals(15, model.intValue);
assertEquals(15, model.longValue);
assertEquals(15, model.floatValue, 0.0001);
assertEquals(15, model.doubleValue, 0.0001);值得注意的是,字符串值不能被反序列化為布爾類型。
4.2. 反序列化空字符串值
另一方面,讓我們嘗試使用以下包含空字符串的 JSON 進行反序列化:
String json = "{\"byteValue\": \"\", \"shortValue\": \"\", "
+ "\"intValue\": \"\", \"longValue\": \"\", \"floatValue\": \"\""
+ ", \"doubleValue\": \"\"}";
Gson gson = new Gson();
gson.fromJson(json, PrimitiveBundleInitialized.class);這會導致 JsonSyntaxException,因為在解析基本類型時,空字符串是不期望出現的。
4.3. 反序列化空值
嘗試反序列化具有值為 null 的字段,Gson 會忽略該字段。例如,使用以下類:
public class PrimitiveBundleInitialized {
public byte byteValue = (byte) 1;
public short shortValue = (short) 1;
public int intValue = 1;
public long longValue = 1L;
public float floatValue = 1.0f;
public double doubleValue = 1;
}Gson 會忽略空字段:
String json = "{\"byteValue\": null, \"shortValue\": null, "
+ "\"intValue\": null, \"longValue\": null, \"floatValue\": null"
+ ", \"doubleValue\": null}";
Gson gson = new Gson();
PrimitiveBundleInitialized model = gson.fromJson(json, PrimitiveBundleInitialized.class);
assertEquals(1, model.byteValue);
assertEquals(1, model.shortValue);
assertEquals(1, model.intValue);
assertEquals(1, model.longValue);
assertEquals(1, model.floatValue, 0.0001);
assertEquals(1, model.doubleValue, 0.0001);4.4. 嘗試反序列化溢出值
如果嘗試反序列化溢出值,則會拋出JsonSyntaxException異常。
使用模型時:
class ByteExample {
public byte value;
}
@Test(expected = JsonSyntaxException.class)
public void whenDeserializingValueThatOverflows_thenShouldRaiseAnException() {
Gson gson = new Gson();
String json = "{\"value\": \"300\"}";
ByteExample model = gson.fromJson(json, ByteExample.class);
}4.5. 反序列化浮點數
接下來,讓我們嘗試將以下 JSON 反序列化為 ByteExample 對象:
{"value": 2.3}Gson 在處理時會正確地拋出 JsonSyntaxException 異常,其子類型為 NumberFormatException。 無論我們使用哪種具體類型(byte、short、int 或 long) ,我們都會得到相同的結果。
如果值以 “.0” 結尾,Gson 將按照預期的方式進行數值解析。
4.6. 反序列化數值布爾值
有時,布爾值會被編碼為 0 或 1,而不是 “true” 或 “false”。Gson 默認情況下不允許這樣做。例如,如果我們嘗試反序列化:
{"value": 1}進入模型:
class BooleanExample {
public boolean value;
}Gson 拋出 JsonSyntaxException,其異常子類型為 IllegalStateException。 這與當數字不匹配時拋出的 NumberFormatException 形成對比。 如果我們想要改變這一點,我們可以使用自定義的序列化器。
4.7. 反序列化 Unicode 字符
需要注意的是,反序列化 Unicode 字符無需進行額外配置。
例如,JSON:
{"value": "\u00AE"}將產生®字符。
5. 結論
正如我們所見,Gson 提供了一種簡單的方法來處理 JSON 和 Java 原始數據類型。即使在處理簡單的原始數據類型時,也存在一些需要注意的意外行為。