Подтвердить что ты не робот

Gson, вызывающий стандартную десериализацию в пользовательском десериализаторе

Можно ли написать json deserializer в 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 (я не могу использовать какую-либо другую версию, так как я могу использовать только версии в корпоративной репозиторий)

спасибо

4b9b3361

Ответ 1

Вы можете сделать это, выполнив пользовательский 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();

Ответ 2

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

Ответ 3

Отъезд http://gsonfire.io

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

Также у него есть много других интересных функций, которые мне нужно с течением времени с Gson.

Ответ 4

Здесь полная реализация основана на неполном ответе, предоставленном @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);
        }
    }
}

Регистрация factory:

Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(new FieldTypeAdapterFactory())
                .create();

Ответ 5

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