2010-10-14 11 views
34

È possibile scrivere un deserializzatore di JSON in gson che richiama prima il comportamento predefinito e quindi posso eseguire alcune operazioni di post sul mio oggetto. Per esempio:gson che richiama la deserializzazione standard nel deserializzatore personalizzato

public class FooDeserializer implements JsonDeserializer<Foo> { 
    public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {  
     Foo foo = context.deserialize(json, typeOfT);//Standard deserialization call????? 
     foo.doSomething(); 
     return foo(); 
    } 
} 

Sto usando GSON 1.3 (non posso usare qualsiasi altra versione come posso usare solo le versioni in repository aziendale)

grazie

+1

capito che c'è un problema generale http://code.google.com/p/google-gson/issues/detail?id=43 – Asim

+3

Bel lavoro Asim. Puoi per favore pubblicare una risposta alla domanda tu stesso e quindi accettare quella risposta in modo che possiamo chiudere questa domanda? Inoltre, è necessario accettare le risposte alle domande precedenti se risolvono il problema. – Zecas

+0

@Kev Per favore riaprire questa domanda. Ovviamente è stato rilevante per almeno 8 persone che hanno dato un upvote, incluso me (la nona persona). – Guy

risposta

3

È possibile farlo mediante l'attuazione di Custom TypeAdapterFactory per il tuo oggetto (ad esempio CustomClass.class) da deserializzare come di seguito.

public class CustomTypeAdapterFactory implements TypeAdapterFactory { 

    public final TypeAdapter create(Gson gson, TypeToken type) { 
    return new TypeAdapter() { 
      @Override 
      public void write(JsonWriter out, Object value) throws IOException { 
       JsonElement tree = delegate.toJsonTree(value); 
       //add code for writing object 
      } 

      @Override 
      public Object read(JsonReader in) throws IOException { 
       JsonElement tree = elementAdapter.read(in); 
       //Add code for reading object 
      } 
     }; 
    } 
    } 

E poi la registrazione con GSON come

Gson gson = new GsonBuilder().registerTypeAdapter(CustomClass.class,new CustomTypeAdapterFactory()).create(); 
+10

E da dove provengono le variabili 'delegate' e' elementAdapter'? – Flawyte

0
public class YourDeserializer<Foo> extends FooDeserializer<Foo> 
{ 
    public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {  
     Foo foo = super.deserialize(json, typeOfT,context); 
     foo.doSomething(); //put logic 
     return foo(); 
    } 
} 
0

Partenza http://gsonfire.io

E 'una libreria ho fatto che si estende GSON per gestire casi come Post-serializzazione e Post-deserializzazione

Inoltre ha molte altre funzioni interessanti di cui avevo bisogno in precedenza e con Gson.

0

Ecco l'implementazione completa basata sulla risposta incompleta fornita da @ user1556622 e la discussione in code.google.com/p/google-gson/issues/detail?id=43.

Come risultato, è possibile serializzare l'elenco degli oggetti astratti Field e deserializzare senza problemi indipendentemente dall'implementazione concreta dello specifico Field e dalla profondità della gerarchia.

class MyClass { //class which we would like to serialiaze/deserialize 
    List<Field> fields; //field is an hierarchy of classes 
} 


/** 
* Purpose of this adapter is simple: 
* 1) put during serialization in all Field objects additional property describing class 
* 2) during deserialization invoke (based on class info) necessary deserializer to create class 
*/ 

public class FieldTypeAdapterFactory implements TypeAdapterFactory { 
    private static final String CLASS_META_KEY="clz"; 
    Gson gson; 
    TypeToken<?> type; 
    TypeAdapter<Field> fieldAdapter; 
    TypeAdapter<JsonElement> elementAdapter; 
    TypeAdapterFactory taf; 

    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { 
     if (!Field.class.isAssignableFrom(type.getRawType())) 
      return null; // this class only serializes 'Field' and its subtypes 

     this.type=type; 
     this.gson=gson; 
     this.taf=this; 
     fieldAdapter = gson.getDelegateAdapter(taf, TypeToken.get(Field.class)); 
     elementAdapter = gson.getAdapter(JsonElement.class); 
     TypeAdapter<T> result = new FieldTypeAdapter<T>(); 
     result.nullSafe(); 
     return result; 
    } 

    class FieldTypeAdapter<T> extends TypeAdapter<T> { 

     public FieldTypeAdapter() { 
     } 

     @Override 
     public void write(JsonWriter out, Object value) throws IOException { 
      if(value instanceof Field) { 
       JsonObject object = fieldAdapter.toJsonTree((Field)value).getAsJsonObject(); 
       object.addProperty(CLASS_META_KEY, value.getClass().getCanonicalName()); 
       elementAdapter.write(out, object); 
      } 
      else { 
       elementAdapter.write(out, (JsonElement) value); 
      } 
     } 

     @Override 
     public T read(JsonReader in) throws IOException { 
      JsonObject object = elementAdapter.read(in).getAsJsonObject(); 
      if (object.has(CLASS_META_KEY)) { 
       String className=object.get(CLASS_META_KEY).getAsString(); 
       try { 
        Class<?> clz = Class.forName(className); 
        TypeAdapter<?> adapter = gson.getDelegateAdapter(taf, TypeToken.get(clz)); 
        return (T) adapter.fromJsonTree(object); 
       } 
       catch (Exception e) { 
        return (T)fieldAdapter.fromJsonTree(object); 
       } 
      } 
      else 
       return (T)elementAdapter.fromJsonTree(object); 
     } 
    } 
} 

Registrazione di fabbrica:

Gson gson = new GsonBuilder() 
       .registerTypeAdapterFactory(new FieldTypeAdapterFactory()) 
       .create(); 
0
public class FooDeserializer implements JsonDeserializer<Foo> { 
public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {  
    Foo foo=new Gson().fromJson(json, Foo.class); // use default Gson object 
    foo.doSomething(); 
    return foo; 
} 
Problemi correlati