使用自定义typeadapter,json中的jsonwriter添加对象

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

然而令我感到困惑的是,如何委托回json序列化…大多数时候我需要这个用于集合,但为了说明这一点 – 假设我有一个对类,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(); } 

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

我有点困惑? 当然这是最常见的用例? 大多数自定义序列化程序将用于奇怪的T或T树之类的列表,你真的不知道列表中的内容,除了它inheritance自T …所以你需要能够委托回来序列化在某种程度上?

无论如何 – 如果有人能告诉我如何编写上述function,我真的很感激!

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

 public class PairSerializer implements JsonSerializer { 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; } } 

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

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

实际上似乎工作 – 获取对象的适配器 – 使用typeadaptorfactory在对象上发现“json”方法,并让该存储远离适配器对象。 对于这样一个明显的用例来说,似乎非常复杂吗?

例如:

 public static @Nullable TypeAdapter> json(final Gson gson) { final TypeAdapter adaptor = gson.getAdapter(Object.class); return new TypeAdapter>() { @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(); } }; } 

有没有人知道更好的方法呢?