Libro de cocina de deserialización de Gson

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á.