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