在本食譜中,我們將探索各種將 JSON 映射為 Java 對象 的方法,使用流行的 Gson 庫。
1. 將 JSON 反序列化為單個基本對象
讓我們從簡單的開始——我們將將一個簡單的 JSON 反序列化為 Java 對象,即 Foo:
public class Foo {
public int intValue;
public String stringValue;
// + standard equals and hashCode implementations
}解決方案如下:
@Test
public void whenDeserializingToSimpleObject_thenCorrect() {
String json = "{"intValue":1,"stringValue":"one"}";
Foo targetObject = new Gson().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "one");
}2. 將 JSON 反序列化為通用對象
接下來,讓我們使用泛型定義一個對象:
public class GenericFoo<T> {
public T theValue;
}將 JSON 解碼為這種類型的對象:
@Test
public void whenDeserializingToGenericObject_thenCorrect() {
Type typeToken = new TypeToken<GenericFoo<Integer>>() { }.getType();
String json = "{"theValue":1}";
GenericFoo<Integer> targetObject = new Gson().fromJson(json, typeToken);
assertEquals(targetObject.theValue, new Integer(1));
}3. 使用包含額外未知字段的 JSON 對象進行反序列化
接下來,讓我們反序列化一些複雜的 JSON,其中包含額外的 未知字段:
@Test
public void givenJsonHasExtraValues_whenDeserializing_thenCorrect() {
String json =
"{"intValue":1,"stringValue":"one","extraString":"two","extraFloat":2.2}";
Foo targetObject = new Gson().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "one");
}如你所見,Gson 會忽略未知的字段,並僅匹配它能夠匹配的字段。
4. 使用非匹配字段名稱反序列化 JSON 到對象
現在,讓我們看看 Gson 如何處理包含字段與我們的 Foo 對象字段不匹配的 JSON 字符串:
@Test
public void givenJsonHasNonMatchingFields_whenDeserializingWithCustomDeserializer_thenCorrect() {
String json = "{"valueInt":7,"valueString":"seven"}";
GsonBuilder gsonBldr = new GsonBuilder();
gsonBldr.registerTypeAdapter(Foo.class, new FooDeserializerFromJsonWithDifferentFields());
Foo targetObject = gsonBldr.create().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 7);
assertEquals(targetObject.stringValue, "seven");
}請注意,我們已註冊了一個 自定義反序列化器——它能夠正確地從 JSON 字符串中解析出字段並將其映射到我們的 Foo:
public class FooDeserializerFromJsonWithDifferentFields implements JsonDeserializer<Foo> {
@Override
public Foo deserialize
(JsonElement jElement, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
JsonObject jObject = jElement.getAsJsonObject();
int intValue = jObject.get("valueInt").getAsInt();
String stringValue = jObject.get("valueString").getAsString();
return new Foo(intValue, stringValue);
}
}5. 將 JSON 數組反序列化為 Java 對象數組
接下來,我們將反序列化 一個 JSON 數組,將其轉換為 Foo 對象類型的 Java 數組:
@Test
public void givenJsonArrayOfFoos_whenDeserializingToArray_thenCorrect() {
String json = "[{"intValue":1,"stringValue":"one"}," +
"{"intValue":2,"stringValue":"two"}]";
Foo[] targetArray = new GsonBuilder().create().fromJson(json, Foo[].class);
assertThat(Lists.newArrayList(targetArray), hasItem(new Foo(1, "one")));
assertThat(Lists.newArrayList(targetArray), hasItem(new Foo(2, "two")));
assertThat(Lists.newArrayList(targetArray), not(hasItem(new Foo(1, "two"))));
}6. 將 JSON 數組反序列化為 Java 集合
接下來,將 JSON 數組直接反序列化為 Java 集合:
@Test
public void givenJsonArrayOfFoos_whenDeserializingCollection_thenCorrect() {
String json =
"[{"intValue":1,"stringValue":"one"},{"intValue":2,"stringValue":"two"}]";
Type targetClassType = new TypeToken<ArrayList<Foo>>() { }.getType();
Collection<Foo> targetCollection = new Gson().fromJson(json, targetClassType);
assertThat(targetCollection, instanceOf(ArrayList.class));
}7. 將 JSON 解析為嵌套對象
接下來,讓我們定義我們的嵌套對象——FooWithInner:
public class FooWithInner {
public int intValue;
public String stringValue;
public InnerFoo innerFoo;
public class InnerFoo {
public String name;
}
}以下是如何反序列化包含此嵌套對象的輸入:
@Test
public void whenDeserializingToNestedObjects_thenCorrect() {
String json = "{\"intValue\":1,\"stringValue\":\"one\",\"innerFoo\":{\"name\":\"inner\"}}";
FooWithInner targetObject = new Gson().fromJson(json, FooWithInner.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "one");
assertEquals(targetObject.innerFoo.name, "inner");
}8. 使用自定義構造函數反序列化 JSON
最後,讓我們看看如何強制在反序列化過程中使用特定的構造函數,而不是默認的無參數構造函數,使用 <em >InstanceCreator</em>:
public class FooInstanceCreator implements InstanceCreator<Foo> {
@Override
public Foo createInstance(Type type) {
return new Foo("sample");
}
}以下是如何在反序列化中使用我們的 FooInstanceCreator 的方法:
@Test
public void whenDeserializingUsingInstanceCreator_thenCorrect() {
String json = "{\"intValue\":1}";
GsonBuilder gsonBldr = new GsonBuilder();
gsonBldr.registerTypeAdapter(Foo.class, new FooInstanceCreator());
Foo targetObject = gsonBldr.create().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "sample");
}請注意,而不是 null,Foo.stringValue 等於 sample,因為我們使用了以下構造函數:
public Foo(String stringValue) {
this.stringValue = stringValue;
}9. 結論
本文介紹瞭如何利用 Gson 庫來解析 JSON 輸入,涵蓋了單對象和多對象場景下的常見用例。