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

В тази готварска книга изследваме различните начини за демаркиране на 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 { 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, който съдържа допълнителни, неизвестни полета :

@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 { @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 Array в Java Array of Objects

След това ще десериализираме 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 Array в Java Collection

След това, json масив директно в 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"); }

Имайте предвид, че вместо null, Foo.stringValue е равен на пример, тъй като използвахме следния конструктор:

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

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

Тези статии показват как да се използва библиотеката Gson за синтактичен анализ на JSON входа - преглед на най-често използваните случаи както за единични, така и за множество обекти.

Внедряването на всички тези примери и кодови фрагменти може да бъде намерено в моя github проект - това е проект, базиран на Eclipse, така че трябва да е лесно да се импортира и да се изпълнява както е.