2013-12-07 21 views
8

Ho le seguenti POJO:GSON e InstanceCreator problema

public interface Shape { 
    public double calcArea(); 
    public double calcPerimeter(); 
} 

public class Rectangle implement Shape { 
    // Various properties of a rectangle 
} 

public class Circle implements Shape { 
    // Various properties of a circle 
} 

public class ShapeHolder { 
    private List<Shape> shapes; 

    // other stuff 
} 

ho nessun problema a trovare GSON per serializzare un'istanza di ShapeHolder a JSON. Ma quando cerco di deserializzare una stringa di quella JSON indietro in un'istanza ShapeHolder, ricevo un errore:

String shapeHolderAsStr = getString(); 
ShapeHolder holder = gson.fromJson(shapeHodlderAsStr, ShapeHolder.class); 

Produce:

Exception in thread "main" java.lang.RuntimeException: Unable to invoke no-args constructor for interface  
net.myapp.Shape. Register an InstanceCreator with Gson for this type may fix this problem. 
    at com.google.gson.internal.ConstructorConstructor$8.construct(ConstructorConstructor.java:167) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:162) 
    ... rest of stack trace ommitted for brevity 

così ho guardato here e iniziato ad attuare il mio ShapeInstanceCreator:

Ma ora sono bloccato: mi viene dato solo uno java.lang.reflect.Type, ma ho davvero bisogno di uno java.lang.Object così ho ca n scrivere come:

public class ShapeInstanceCreator implements InstanceCreator<Shape> { 
    @Override 
    public Shape createInstance(Type type) { 
     Object obj = convertTypeToObject(type); 

     if(obj instanceof Rectangle) { 
      Rectangle r = (Rectangle)obj; 
      return r; 
     } else { 
      Circle c = (Circle)obj; 
      return c; 
     } 

     return null; 
    } 
} 

Cosa posso fare? Grazie in anticipo!

UPDATE:

Per @ di raffian suggerimento (il link lui/lei postato), ho implementato un InterfaceAdapteresattamente come quello nel link (Non ho cambiato nulla ). Ora sto ottenendo la seguente eccezione:

Exception in thread "main" com.google.gson.JsonParseException: no 'type' member found in what was expected to be an interface wrapper 
    at net.myapp.InterfaceAdapter.get(InterfaceAdapter.java:39) 
    at net.myapp.InterfaceAdapter.deserialize(InterfaceAdapter.java:23) 

Qualche idea?

+0

Controlla questo: http://stackoverflow.com/a/19600090/1360888, ha una classe base anziché un'interfaccia ma è come il tuo problema. – giampaolo

risposta

4

Hai guardato this? Sembra un bel modo pulito per implementare InstanceCreators.

Anche io stavo usando Gson, ma sono passato a FlexJSON a causa di problemi di serializzazione. Con Flex, non hai bisogno di creatori esempio, basta assicurarsi che gli oggetti hanno getter/setter per tutti i campi sulla base di JavaBean spec, e siete pronti ad andare:

ShapeHolder sh = new ShapeHolder(); 
sh.addShape(new Rectangle()); 
sh.addShape(new Circle()); 
JSONSerializer ser = new JSONSerializer(); 
String json = ser.deepSerialize(sh); 
JSONDeserializer<ShapeHolder> der = new JSONDeserializer<ShapeHolder>(); 
ShapeHolder sh2 = der.deserialize(json); 
+0

Grazie @raffian (+1) - Ho creato un 'InterfaceAdapter' come nell'esempio mostrato nel link che hai postato. L'ho registrato come adattatore di tipo con 'GsonBuilder' (di nuovo come nell'esempio). Ora sto ricevendo un nuovo errore (vedi la mia domanda aggiornata). Qualche idea su cosa sta succedendo adesso? Grazie ancora! – IAmYourFaja

+0

Non mi scuso, questo è il motivo per cui sono passato al flex, per evitare tutta questa merda! :-) C'è qualche costrizione che ti costringe a usare Gson? – raffian

+0

Ci scusiamo per la risposta ritardata - Sono andato a letto e ho appena fatto un giro a FlexJSON. Che meraviglia! Immagina questo: serializzazione/deserializzazione che "funziona" appena fuori dalla scatola! Mi hai sicuramente convertito - grazie! – IAmYourFaja

0

NOTA che FlexJSON sta aggiungendo il nome della classe come parte di json come sotto serializza il tempo.

{ 
    "HTTPStatus": "OK", 
    "class": "com.XXX.YYY.HTTPViewResponse", 
    "code": null, 
    "outputContext": { 
     "class": "com.XXX.YYY.ZZZ.OutputSuccessContext", 
     "eligible": true 
    } 
} 

Quindi JSON sarà un po 'di sperma; ma non è necessario scrivere InstanceCreator che è richiesto in GSON.