Contents

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 Collection

@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

最后,让我们看看如何在反序列化期间强制使用特定的构造函数,而不是使用默认构造函数——无参数构造函数——使用InstanceCreator

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");
}

请注意,Foo.stringValue不是 null,而是等于示例,因为我们使用了以下构造函数:

public Foo(String stringValue) {
    this.stringValue = stringValue;
}