【问题标题】:gson invoking standard deserialization in custom deserializergson 在自定义反序列化器中调用标准反序列化
【发布时间】:2011-04-25 08:43:50
【问题描述】:

是否可以在 gson 中编写一个 json 反序列化器,它首先调用默认行为,然后我可以对我的对象进行一些后期处理。例如:

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(我不能使用任何其他版本,因为我只能使用公司中的版本 存储库)

谢谢

【问题讨论】:

  • 意识到有一个普遍的问题code.google.com/p/google-gson/issues/detail?id=43
  • 干得好阿西姆。您能否自行发布该问题的答案,然后接受该答案以便我们结束该问题?此外,如果他们解决了您的问题,您需要接受之前问题的答案。
  • @Kev 请重新打开这个问题。显然,至少有 8 个人对它投了赞成票,包括我(第 9 个人)。
  • @Guy - 有点“为我写这段代码”,这就是为什么它被标记为 mod 注意,然后我关闭了它。受欢迎程度并不总是一个好的问题的一个很好的指标,我相信你会知道的。请注意,我去年作为钻石模组退休了,所以我无法重新提出问题。只有另一个具有足够权限的钻石模组或用户组才能重新打开。 OP 也可以标记为重新打开,以便他/她可以发布答案。
  • 好问题。如果我有时间我会尝试稍后解决它

标签: java json gson


【解决方案1】:

您可以通过为要反序列化的对象(例如 CustomClass.class)实现自定义 TypeAdapterFactory 来做到这一点,如下所示。

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

【讨论】:

  • 那么delegateelementAdapter 变量从何而来?
  • @flawyte,此示例在return new TypeAdapter 之前缺少一行:委托适配器创建。这可以是一个内置适配器,例如,final TypeAdapter&lt;T&gt; delegate = TypeAdapters.ENUM_FACTORY.create(gson, type);
【解决方案2】:
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;
}

【讨论】:

  • 在每次反序列化时分配新的 Gson 实例是个坏主意。
【解决方案3】:

查看http://gsonfire.io

这是我创建的一个库,它扩展了 Gson 以处理后序列化和后反序列化等情况

此外,它还有许多其他很酷的功能,随着时间的推移我需要 Gson。

【讨论】:

    【解决方案4】:
    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();  
        }  
    }  
    

    【讨论】:

      【解决方案5】:

      这是基于@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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-10
        • 2018-01-01
        • 1970-01-01
        • 2020-09-09
        • 1970-01-01
        • 2013-03-09
        相关资源
        最近更新 更多