2013-10-18 12 views
5

Sulla mia applicazione Java, ho definito due classi, chiamate A e B dove B è la classe interna di A. Entrambi sono definiti come serializzabileGSON non deserializza il riferimento alla classe esterna

public class A implements Serializable { 

    int attrParent; 
    List<B> items = new ArrayList<B>(); 

    public void setAttrParent(int attrParent) { 
     this.attrParent = attrParent; 
    } 

    public int getAttrParent() { 
     return attrParent; 
    } 

    public class B implements Serializable { 

     private int attr; 

     public void setAttr(int attr) { 
      this.attr = attr; 
     } 

     public int getAttr() { 
      return attr; 
     } 

     public int getSomeCalculationValue() { 
      return this.attr * A.this.attrParent; // Problems occurs here 
     } 

    } 
} 

Prima serializzazione questo oggetto con GSON, getSomeCalculationValue funziona bene. Ma, dopo la serializzazione e deserializzazione, getSomeCalculationValue non riesce con uno NullPointerException.

Questo accade perché la classe interna B non ha più un riferimento alla classe esterna A, quindi, A.this non riesce.

Qualcuno sa come potrei risolvere questo, cioè ripristinare l'interiore al riferimento esterno mentre deserializza questo oggetto?

+0

Si prega di mostrare il processo di serializzazione e deserializzazione, nonché un campione gson. Non vedo perché hai bisogno di 'Serializable' qui. –

risposta

6

Come documentazione GSON dice:

GSON può serializzare classi annidate statiche abbastanza facilmente.

Gson può anche deserializzare classi nidificate statiche. Tuttavia, Gson può non deserializzare automaticamente le classi interne pure poiché il loro costruttore di no-args necessita anche di un riferimento all'oggetto contenente che non è disponibile al momento della deserializzazione. È possibile risolvere questo problema con rendendo statica la classe interna o tramite fornendo un InstanceCreator personalizzato per esso.

Cambiare B a una classe interna statica non è possibile in quanto il metodo ha bisogno di un riferimento alla classe esterna in getSomeCalculationValue, così, ho cercato di risolvere il problema con una InstanceCreator ma soluzione è stata un po 'brutto, così Ti propongo di usare una deserializzazione personalizzata. Ho modificato la tua classe A un po ', rendendo pubblici gli elementi per semplificare la creazione dell'esempio che ti mostro.

public class ADeserializer implements JsonDeserializer<A> { 
    public A deserialize(JsonElement json, Type typeOfT, 
     JsonDeserializationContext context) throws JsonParseException { 

    A a = new A(); 
    a.attrParent = json.getAsJsonObject().get("attrParent").getAsInt(); 
    JsonArray ja = json.getAsJsonObject().get("items").getAsJsonArray(); 
    for(JsonElement e: ja){ 
     B b = a.new B(); 
     b.setAttr(e.getAsJsonObject().get("attr").getAsInt()); 
     a.items.add(b); 
    } 
    return a; 
    } 

} 

E questo è come lo uso:

public class Q19449761 { 

    public static void main(String[] args) { 

     A a = new A(); 
     a.setAttrParent(3); 
     B b = a.new B(); 
     b.setAttr(10); 
     a.items.add(b); 
     System.out.println("Before serializing: " + a.items.get(0).getSomeCalculationValue()); 

     Gson g = new Gson(); 

     String json = g.toJson(a, A.class); 
     System.out.println("JSON string: " + json); 

     A test2 = g.fromJson(json, A.class); 

     try { 
      System.out.println("After standard deserialization: " +test2.items.get(0).getSomeCalculationValue()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     GsonBuilder builder = new GsonBuilder(); 
     builder.registerTypeAdapter(A.class, new ADeserializer()); 

     A test3 = builder.create().fromJson(json, A.class); 

     System.out.println("After custom deserialization: " + test3.items.get(0).getSomeCalculationValue()); 

    } 

} 

E questa è la mia esecuzione:

Before serializing: 30 
JSON string: {"attrParent":3,"items":[{"attr":10}]} 
java.lang.NullPointerException 
    at stackoverflow.questions.q19449761.A$B.getSomeCalculationValue(A.java:32) 
    at stackoverflow.questions.q19449761.Q19449761.main(Q19449761.java:26) 
After custom deserialization: 30 

Due note finali:

  1. Non è necessario implementare l'interfaccia Serializable, JSON non ha nulla in comune con Ja serializzazione va
  2. Il mio deserializzatore manca di gestione dei casi null, è necessario completare per campi JSON null o null.
+0

"interno statico" è una contraddizione in termini. – EJP

Problemi correlati