Поваренная книга десериализации 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.
Gson Serialization Cookbook
Узнайте, как сериализовать сущности, используя библиотеку Gson.
Джексон против Гсона
Краткое и практическое руководство по сериализации с Джексоном и Гсоном.
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, поэтому его должно быть легко импортировать и запускать как есть.