【问题标题】:adding an object using a custom typeadapter, jsonwriter in gson在 gson 中使用自定义类型适配器、jsonwriter 添加对象
【发布时间】:2013-06-05 00:49:10
【问题描述】:

gson 是一个很棒的库 - 它运行良好。有时我有自定义要求,可以制作和注册 TypeAdapters 和 TypeAdaptorFactories - 这也很有效。

然而,让我感到困惑的是,如何委托回 json 序列化...大多数时候我需要这个来进行集合,但为了说明这一点 - 假设我有一个 pair 类,gson 显然会愉快地序列化,但是出于某种原因,我需要自己的自定义序列化程序。好吧...如果我的那对是

public class Pair
{
    public final Object First;
    public final Object Second; 
    public Pair( Object first, Object second) {this.first = first; this.second = second};
}

如果我为此编写了一个类型适配器 - 你会希望 write 函数看起来像:

public void write( JsonWriter out, Pair pair )
{
    out.beginObject();
    out.name( "first");
    out.value( pair.first );         // can't do this
    out.name( "second");
    out.value( pair.second);         // or this
    out.endObject();
}

所以你可以看到问题 - 我不知道 first 和 second 的类型,也不知道它们是如何序列化的。我可以使用 gson.toJson 序列化第一个和第二个 - 但如果我将它们作为字符串添加到编写器,它们将被转义。有一个 gson.tojson 函数需要一个值和一个 writer - 但它也需要一个 typetoken - 我没有。我有点印象,我打算从某个地方拥有另一种类型的适配器 - 但是当我只有一个对象列表时......我从哪里得到那个?我只是得到对象的适配器吗?

我有点困惑?这肯定是最常见的用例吗?大多数自定义序列化程序将用于一个奇怪的 T 列表或 T 的树或其他东西,并且您真的不知道列表中的内容,除此之外它从 T 继承......所以您需要能够委托回以某种方式序列化?

无论如何 - 如果有人能告诉我如何编写上述函数,我将不胜感激!

【问题讨论】:

    标签: java json gson


    【解决方案1】:

    实际上这似乎可行 - 获取对象的适配器 - 使用 typeadaptorfactory 发现对象上的“json”方法,并将其存储起来适配器对象。对于如此明显的用例来说,这似乎是惊人的复杂?

    例如:

    public static @Nullable
    TypeAdapter<ImmutableStack<?>> json(final Gson gson)
    {
        final TypeAdapter<Object> adaptor = gson.getAdapter(Object.class);
        return new TypeAdapter<ImmutableStack<?>>()
        {
            @Override
            public ImmutableStack<?> read(@Nullable final JsonReader in) throws IOException
            {
                throw ProgramError.notImplementedYet();
            }
            @Override
            public void write(final JsonWriter out, final ImmutableStack<?> value) throws IOException
            {
                out.beginArray();
                for (final Object inner : value)
                    adaptor.write(out, inner);
                out.endArray();
            }
        };
    }
    

    有人知道更好的方法吗?

    【讨论】:

      【解决方案2】:

      在这种情况下,最好使用JsonSerializer 而不是TypeAdapter,原因很简单,序列化程序可以访问其序列化上下文:

      public class PairSerializer implements JsonSerializer<Pair> {
      
          public PairSerializer() {
              super();
          }
      
          @Override
          public JsonElement serialize(final Pair value, final Type type,
                  final JsonSerializationContext context) {
              final JsonObject jsonObj = new JsonObject();
              jsonObj.add("first", context.serialize(value.getFirst()));
              jsonObj.add("second", context.serialize(value.getSecond()));
      
              return jsonObj;
          }
      }
      

      上面的示例代码说明了如何将目标对象的序列化委托回主编组器。这样做的主要优点(除了避免复杂的解决方法)是您仍然可以利用可能已在主上下文中注册的其他类型适配器和自定义序列化程序。请注意,序列化程序和适配器的注册使用完全相同的代码:

      // With adapter
      final Gson gson = new GsonBuilder().registerTypeAdapter(Pair.class,
              new PairAdapter()).create();
      
      // With serializer
      final Gson gson = new GsonBuilder().registerTypeAdapter(Pair.class,
              new PairSerializer()).create();
      

      如果您发现需要坚持使用适配器,则可以使用嵌入式 Gson 代理为您序列化 Pair 属性,缺点是您无法访问在父 Gson 代理上进行的自定义注册:

      public class PairAdapter extends TypeAdapter<Pair> {
          final Gson embedded = new Gson();
      
          public PairAdapter() {
              super();
          }
      
          @Override
          public void write(final JsonWriter out, final Pair value)
                  throws IOException {
              out.beginObject();
      
              out.name("first");
              embedded.toJson(embedded.toJsonTree(value.getFirst()), out);
      
              out.name("second");
              embedded.toJson(embedded.toJsonTree(value.getSecond()), out);
      
              out.endObject();
          }
      
          @Override
          public Pair read(JsonReader in) throws IOException {
              throw new UnsupportedOperationException();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-12
        相关资源
        最近更新 更多