2010-10-14 5 views
34

Возможно ли записать json deserializer в gson, который сначала вызывает поведение по умолчанию, а затем я могу выполнить некоторую пост-обработку на моем объекте. Например:gson вызывает стандартную десериализацию в пользовательском десериализаторе

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(); 
    } 
} 

Я использую gson 1,3 (я не могу использовать любой другой вариант, как я могу использовать только версии в корпоративном хранилище)

благодаря

+1

Понял, что существует общая проблема http://code.google.com/p/google-gson/issues/detail?id=43 – Asim

+3

Хорошая работа Asim. Можете ли вы отправить ответ на вопрос самостоятельно, а затем принять этот ответ, чтобы мы могли закрыть этот вопрос? Кроме того, вам необходимо принять ответы на предыдущие вопросы, если они исправит вашу проблему. – Zecas

+0

@Kev Пожалуйста, повторно откройте этот вопрос. Очевидно, что у него хватило 8 человек, что дало ему преимущество, включая меня (9-го человека). – Guy

ответ

3

Вы можете сделать это путем внедрения пользовательский TypeAdapterFactory для вашего объекта (скажем, CustomClass.class), который будет десериализован, как показано ниже.

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 
      } 
     }; 
    } 
    } 

А потом его регистрации с Gson в

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

И откуда берутся переменные 'делегат' и' 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

Заканчивать http://gsonfire.io

Это библиотека Я сделал, что расширяет Gson обрабатывать случаи, как пост-сериализации и пост-десериализации

Также у этого есть много других интересных функций, которые мне нужны были во время с Гсоном.

0

Вот полная реализация, основанная на неполном ответе, предоставленном @ user1556622, и обсуждении в code.google.com/p/google-gson/issues/detail?id=43.

В результате мы можем сериализовать список абстрактных объектов Field и плавно десериализировать его независимо от конкретной реализации конкретного Field и глубины его иерархии.

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

Регистрация завода:

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; 
}