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