En este libro de cocina, exploramos las diversas formas de descomponer JSON en objetos Java , utilizando la popular biblioteca Gson.
1. Deserializar JSON en un solo objeto básico
Comencemos de manera simple: vamos a deshacer un json simple en un objeto Java: Foo :
public class Foo { public int intValue; public String stringValue; // + standard equals and hashCode implementations }
Y la solucion:
@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. Deserializar JSON en un objeto genérico
A continuación, definamos un objeto usando genéricos:
public class GenericFoo { public T theValue; }
Y deshaga algunos json en este tipo de objeto:
@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. Deserializar JSON con campos desconocidos adicionales al objeto
A continuación, deserialicemos un json complejo que contiene campos desconocidos adicionales :
@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"); }
Como puede ver, Gson ignorará los campos desconocidos y simplemente hará coincidir los campos que pueda.
4. Deserializar JSON con nombres de campo que no coincidan con el objeto
Ahora, veamos cómo le va a Gson con una cadena json que contiene campos que simplemente no coinciden con los campos de nuestro objeto 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"); }
Tenga en cuenta que registramos un deserializador personalizado ; esto fue capaz de analizar correctamente los campos de la cadena json y asignarlos a nuestro 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. Deserializar JSON Array a Java Array of Objects
A continuación, vamos a deserializar una matriz json en una matriz Java de objetos 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. Deserializar JSON Array a Java Collection
A continuación, una matriz json directamente en una colección de Java :
@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. Deserializar JSON en objetos anidados
A continuación, definamos nuestro objeto anidado - FooWithInner :
public class FooWithInner { public int intValue; public String stringValue; public InnerFoo innerFoo; public class InnerFoo { public String name; } }
Y aquí se explica cómo deserializar una entrada que contiene este objeto anidado:
@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. Deserializar JSON mediante el constructor personalizado
Finalmente, veamos cómo forzar el uso de un constructor específico durante las deserializaciones en lugar del constructor predeterminado, sin argumentos, usando InstanceCreator :
public class FooInstanceCreator implements InstanceCreator { @Override public Foo createInstance(Type type) { return new Foo("sample"); } }
Y aquí se explica cómo utilizar nuestro FooInstanceCreator en la deserialización:
@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"); }
Tenga en cuenta que en lugar de nulo, Foo.stringValue es igual a la muestra, ya que usamos el siguiente constructor:
public Foo(String stringValue) { this.stringValue = stringValue; }
9. Conclusión
Este artículo muestra cómo aprovechar la biblioteca Gson para analizar la entrada JSON , repasando los casos de uso más comunes para objetos únicos y múltiples.
La implementación de todos estos ejemplos y fragmentos de código se puede encontrar en mi proyecto github ; este es un proyecto basado en Eclipse, por lo que debería ser fácil de importar y ejecutar tal como está.