Поваренная книга по десериализации Gson

Поваренная книга десериализации Gson

В этой поваренной книге мы исследуем различные способыunmarshall JSON into Java objects, используя популярныйGson library.

1. Десериализовать JSON в один базовый объект

Начнем с простого - перейдем кunmarshall a simple json to a Java object – 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");
}

Дальнейшее чтение:

Исключить поля из сериализации в Gson

Изучите доступные варианты исключения полей из сериализации в Gson.

Read more

Gson Serialization Cookbook

Узнайте, как сериализовать сущности, используя библиотеку Gson.

Read more

Джексон против Гсона

Краткое и практическое руководство по сериализации с Джексоном и Гсоном.

Read more

2. Десериализовать JSON в универсальный объект

Далее - давайте определим объект с помощью дженериков:

public class GenericFoo {
    public T theValue;
}

И удалите некоторый JSON в этот тип объекта:

@Test
public void whenDeserializingToGenericObject_thenCorrect() {
    Type typeToken = new TypeToken>() { }.getType();
    String json = "{"theValue":1}";

    GenericFoo targetObject = new Gson().fromJson(json, typeToken);

    assertEquals(targetObject.theValue, new Integer(1));
}

3. Десериализовать JSON с дополнительными неизвестными полями для объекта

Далее - давайте десериализуем некоторый сложный json, который содержит дополнительныеunknown fields:

@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 will ignore the unknown fields и просто сопоставьте поля, которые он может.

4. Десериализовать JSON с несовпадающими именами полей для объекта

Теперь давайте посмотрим, как работает 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");
}

Обратите внимание, что мы зарегистрировалиa custom deserializer - он смог правильно проанализировать поля из строки json и сопоставить их с нашимFoo:

public class FooDeserializerFromJsonWithDifferentFields implements JsonDeserializer {

    @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

Затем мы собираемся десериализоватьa json array into a Java array объектовFoo:

@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

Затем массив jsondirectly into a Java Collection:

@Test
public void givenJsonArrayOfFoos_whenDeserializingCollection_thenCorrect() {
    String json =
      "[{"intValue":1,"stringValue":"one"},{"intValue":2,"stringValue":"two"}]";
    Type targetClassType = new TypeToken>() { }.getType();

    Collection 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 {

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

Обратите внимание, что вместо nullFoo.stringValue равноsample, поскольку мы использовали следующий конструктор:

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

9. Заключение

В этой статье показано, как использовать библиотеку Gson дляparse JSON input - рассмотрим наиболее распространенные варианты использования как для одного, так и для нескольких объектов.

Реализация всех этих примеров и фрагментов кодаcan be found in my github project - это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.