Gson Deserialization Cookbook – Gson反序列化手册

最后修改: 2014年 8月 23日

中文/混合/英文(键盘快捷键:t)

In this cookbook, we’re exploring the various ways to unmarshall JSON into Java objects, using the popular Gson library.

在本食谱中,我们将使用流行的Gson库,探索将JSON解压缩为Java对象的各种方法。

1. Deserialize JSON to Single Basic Object

1.将JSON反序列化为单一基本对象

Let’s start simple – we’re going to unmarshall a simple json to a Java object – Foo:

让我们从简单的开始–我们将解读一个简单的json到一个Java对象–Foo

public class Foo {
    public int intValue;
    public String stringValue;

    // + standard equals and hashCode implementations
}

And the solution:

以及解决方案。

@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. Deserialize JSON to Generic Object

2.将JSON反序列化为通用对象

Next – let’s define an object using generics:

接下来–让我们使用泛型定义一个对象。

public class GenericFoo<T> {
    public T theValue;
}

And unmarshall some json into this type of object:

并将一些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. Deserialize JSON With Extra Unknown Fields to Object

3.将带有额外未知字段的JSON反序列化为对象

Next – let’s deserialize some complex json that contains additional, unknown fields:

接下来–让我们对一些复杂的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");
}

As you can see, Gson will ignore the unknown fields and simply match the fields that it’s able to.

正如你所看到的,Gson会忽略未知的字段,只是简单地匹配它能够匹配的字段。

4. Deserialize JSON With Non-Matching Field Names to Object

4.将字段名不匹配的JSON反序列化为对象

Now, let’s see how Gson does with a json string containing fields that simply don’t match the fields of our Foo object:

现在,让我们看看Gson是如何处理一个包含字段的json字符串的,该字符串与我们的Foo对象的字段根本不匹配。

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

Notice that we registered a custom deserializer – this was able to correctly parse out the fields from the json string and map them to our Foo:

请注意,我们注册了一个自定义反序列化器–它能够正确解析出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. Deserialize JSON Array to Java Array of Objects

5.将JSON数组反序列化为对象的Java数组

Next, we’re going to deserialize a json array into a Java array of Foo objects:

接下来,我们要把一个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. Deserialize JSON Array to Java Collection

6.将JSON数组反序列化为Java集合

Next, a json array directly into a Java Collection:

接下来,一个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. Deserialize JSON to Nested Objects

7.将JSON反序列化为嵌套对象

Next, let’s define our nested object – FooWithInner:

接下来,让我们定义我们的嵌套对象 – FooWithInner

public class FooWithInner {
    public int intValue;
    public String stringValue;
    public InnerFoo innerFoo;

    public class InnerFoo {
        public String name;
    }
}

And here is how to deserialize an input containing this nested object:

而这里是如何反序列化一个包含这个嵌套对象的输入。

@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. Deserialize JSON Using Custom Constructor

8.使用自定义构造函数对JSON进行反序列化

Finally, let’s see how to force using a specific constructor during deserializations instead of default – no arguments constructor – using InstanceCreator:

最后,让我们看看如何使用InstanceCreator在反序列化过程中强制使用一个特定的构造函数,而不是默认的无参数构造函数。

public class FooInstanceCreator implements InstanceCreator<Foo> {

    @Override
    public Foo createInstance(Type type) {
        return new Foo("sample");
    }
}

And here is how to use our FooInstanceCreator in deserialization:

而这里是如何在反序列化中使用我们的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");
}

Note that instead of null, the Foo.stringValue equals sample as we used the following constructor:

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

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

9. Conclusion

9.结论

This articles shows how to leverage the Gson library to parse JSON input – going over the most common usecases for both single and multiple objects.

这篇文章展示了如何利用Gson库来解析JSON输入–介绍了单个和多个对象的最常见的使用情况。

The implementation of all these examples and code snippets can be found in my github project – this is an Eclipse based project, so it should be easy to import and run as it is.

所有这些例子和代码片段的实现可以在我的Github项目中找到 – 这是一个基于Eclipse的项目,所以应该很容易导入并按原样运行。