Jackson – problema con Maps e valori null

In questo articolo vorrei dare una soluzione ad un problema che si presenta svariate volte per chi sviluppa in JAVA.

Nel momento in cui ci si trova a manipolare il formato JSON (JavaScript Object Notation) per la trasmissione di dati possono sorgere dei problemi.

Infatti, per poter lavorare su questa tipoligia di dati, esistono svariate librerie in JAVA (chi meglio e chi peggio) che permettono di poter effettuare molte operazioni su un file JSON;

Tra tutte le librerie disponibili a mio parere il miglior parser JSON esistente al momento non è altro che Jackson.

Ignorare valori “null” in una Map

Jackson ha un semplice funzionamento e permette di trasformare un determinato dato da un formato JSON ad un formato a nostro piacimento (Bean, List, Map ecc.) e viceversa.

I problemi però possono sorgere nel momento in cui alcuni dati presenti nel JSON hanno un valore null.

Tutto ciò per il semplice fatto che al momento della conversione non viene trovato il corrispondente valore all’interno dell’oggetto JAVA.

Per superare questo inconveniente è necessario inserire una semplice riga dopo l’instanziamento dell’ObjectMapper:

 ObjectMapper mapper = new ObjectMapper(); 
 mapper.setSerializationInclusion(Include.NON_NULL);

Inserendo semplicemente la riga in rosso nel pezzo di codice precedente non si fa altro che indicare al parser di ignorare ogni valore null presente ed andare avanti nell’elaborazione.

Serializzazione Map con chiave “null”

Di default, Jackson non permette la serializzazzione di una Map in Java che contiene una chiave con valore null.

Infatti, se si vuole verificare tale affermazione basta creare una Map e assegnare dei valori, facendo in modo che sia presente almeno una chiave con valore null, come nell’esempio seguente:

 ObjectMapper mapper = new ObjectMapper(); 
 PersonaTO to= new PersonaTO(); 
 to.setValue("valorePersona"); 
 Map<String,PersonaTO> map = new HashMap<String,PersonaTO>(); 
 map.put(1,to); 
 map.put(null,to);
 String mapToString = mapper.writeValueAsString(dtoMap); 

Eseguendo il pezzo di codice precedente si avrà un errore in fase di esecuzione del tipo:

c.f.j.c.JsonGenerationException:  
  Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)     
			at c.f.j.d.s.i.FailingSerializer.serialize(FailingSerializer.java:36)

Soluzione

Per risolvere tale errore, basta semplicemente sovrascrivere il metodo serialize della classe StdSerializer presente nelle librerie di Jackson:

class MySerializer extends StdSerializer<Object> {     
		public MyDtoNullKeySerializer() {
             this(null);}     
			 public MySerializer(Class<Object> t) { 
				super(t);     
			}     
	  @Override   
	  public void serialize(Object nullKey, JsonGenerator jsonGenerator,SerializerProvider unused) 
		  throws IOException, JsonProcessingException { 
			jsonGenerator.writeFieldName("");    
		} 
}

Fatto ciò è possibile modificare il metodo di test precedente nel seguente modo:

  ObjectMapper mapper = new ObjectMapper(); 
  mapper.getSerializerProvider().setNullKeySerializer(new MySerializer()); 
  PersonaTO to= new PersonaTO(); 
  to.setValue("valorePersona");  
  Map<String, PersonaTO> map = new HashMap<String, PersonaTO>(); 
  map.put(1, to);  
  map.put(null, to);  
  String mapToString = mapper.writeValueAsString(dtoMap);

Facendo ciò, adesso, nel momento della conversione non verrà pià chiamato il metodo serialize di default di Jackson, bensi quello sovrascritto da noi, ignorando cosi i valori null presenti all’interno di una chiave della Map.