«В этой кулинарной книге мы изучаем различные способы преобразования 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 работает со строкой 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");
}

Обратите внимание, что мы зарегистрировали собственный десериализатор — он смог правильно проанализировать поля из строки 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 в массив Java объектов 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

Далее, массив 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 с помощью пользовательского конструктора

Наконец, давайте посмотрим, как принудительно использовать определенный конструктор во время десериализации вместо конструктора по умолчанию — без аргументов — с помощью InstanceCr. eator:

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 равняется образцу, поскольку мы использовали следующий конструктор:

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

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

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

Реализацию всех этих примеров и фрагментов кода можно найти в моем проекте на github — это проект на основе Eclipse, поэтому его легко импортировать и запускать как есть.