Ricettario sulla deserializzazione di Gson

In questo libro di cucina, stiamo esplorando i vari modi per unmarshalling JSON in oggetti Java , utilizzando la popolare libreria Gson.

1. Deserializza JSON in un singolo oggetto di base

Iniziamo in modo semplice: unmarshalling un semplice json in un oggetto Java - Foo :

public class Foo { public int intValue; public String stringValue; // + standard equals and hashCode implementations }

E la soluzione:

@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. Deserializza JSON in un oggetto generico

Avanti - definiamo un oggetto usando i generici:

public class GenericFoo { public T theValue; }

E unmarshall alcuni json in questo tipo di oggetto:

@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. Deserializza JSON con campi sconosciuti aggiuntivi in ​​Object

Avanti: deserializziamo alcuni json complessi che contengono campi aggiuntivi sconosciuti :

@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"); }

Come puoi vedere, Gson ignorerà i campi sconosciuti e abbinerà semplicemente i campi che è in grado di fare.

4. Deserializza JSON con nomi di campo non corrispondenti all'oggetto

Ora, vediamo come fa Gson con una stringa json contenente campi che semplicemente non corrispondono ai campi del nostro oggetto 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"); }

Si noti che abbiamo registrato un deserializzatore personalizzato : questo è stato in grado di analizzare correttamente i campi dalla stringa json e mapparli al nostro 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. Deserializza array JSON in array di oggetti Java

Successivamente, deserializzeremo un array json in un array Java di oggetti 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. Deserializza array JSON in raccolta Java

Successivamente, un array json direttamente in una raccolta 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. Deserializza JSON in oggetti nidificati

Successivamente, definiamo il nostro oggetto annidato - FooWithInner :

public class FooWithInner { public int intValue; public String stringValue; public InnerFoo innerFoo; public class InnerFoo { public String name; } }

Ed ecco come deserializzare un input contenente questo oggetto annidato:

@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. Deserializza JSON utilizzando il costruttore personalizzato

Infine, vediamo come forzare l'uso di un costruttore specifico durante le deserializzazioni invece del costruttore predefinito - nessun costruttore di argomenti - usando InstanceCreator :

public class FooInstanceCreator implements InstanceCreator { @Override public Foo createInstance(Type type) { return new Foo("sample"); } }

Ed ecco come utilizzare il nostro FooInstanceCreator nella deserializzazione:

@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"); }

Nota che invece di null, Foo.stringValue è uguale a sample poiché abbiamo utilizzato il seguente costruttore:

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

9. Conclusione

Questo articolo mostra come sfruttare la libreria Gson per analizzare l'input JSON, esaminando i casi d'uso più comuni per oggetti singoli e multipli.

L'implementazione di tutti questi esempi e frammenti di codice può essere trovata nel mio progetto GitHub : questo è un progetto basato su Eclipse, quindi dovrebbe essere facile da importare ed eseguire così com'è.