简体   繁体   English

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

[英]adding an object using a custom typeadapter, jsonwriter in gson

gson is a great library - it works well. gson是一个很棒的图书馆 - 它运作良好。 Sometimes I have custom requirements, and can make and register TypeAdapters and TypeAdaptorFactories - and that works well too. 有时我有自定义要求,可以制作和注册TypeAdapters和TypeAdaptorFactories - 这也很有效。

What confuses me however, is how to delegate back into json serialization... Most of the time I need this for collections, but to illustrate the point - suppose I had a pair class, which gson would obviously serialize happily, but for some reason I needed my own custom serializer. 然而令我困惑的是,如何委托回json序列化...大多数时候我需要这个用于集合,但为了说明这一点 - 假设我有一个对类,gson显然会愉快地序列化,但由于某种原因我需要自己的自定义序列化程序。 Well... if my pair is 好吧......如果我的配对是

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

If I wrote a type adapter for this - you would want the write function to look like: 如果我为此编写了一个类型适配器 - 您希望 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();
}

So you can see the problem - I have no idea the type of first and second, nor how they are serialized. 所以你可以看到问题 - 我不知道第一个和第二个的类型,也不知道它们是如何序列化的。 I can use gson.toJson to serialize first and second - but if I add them as a string to the writer, they will be escaped. 我可以使用gson.toJson来序列化第一个和第二个 - 但是如果我将它们作为字符串添加到编写器中,它们将被转义。 There is a gson.tojson function that takes a value and a writer - but it also takes a typetoken - which I don't have. 有一个gson.tojson函数,它接受一个值和一个编写器 - 但它也需要一个typetoken - 我没有。 I sort of get the impression I'm meant to have another type adapter from somewhere - but when I just have a list of objects... where do I get that? 我得到的印象是,我打算从某个地方安装另一个类型的适配器 - 但是当我只有一个对象列表时......我从哪里得到它? do I just get the adapter for object? 我只是获得对象的适配器?

I'm a little confused? 我有点困惑? Surely this is the most common use case? 当然这是最常见的用例? Most custom serializers will be for a strange list of T or tree of T or something, and you really don't know what is in the list, beyond that it inherits from T... so you need to be able to delegate back the serialization in some way? 大多数自定义序列化程序将用于T或T树之类的奇怪列表,并且你真的不知道列表中的内容,除了它继承自T ...所以你需要能够委托回来序列化在某种程度上?

Anyway - if someone can tell me how to write the above function, I'd really appreciate it! 无论如何 - 如果有人能告诉我如何编写上述功能,我真的很感激!

In this case its better to use a JsonSerializer as opposed to a TypeAdapter , for the simple reason that serializers have access to their serialization context: 在这种情况下,最好使用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;
    }
}

The above sample code illustrates how to delegate serialization of target objects back to the main marshaller. 上面的示例代码说明了如何将目标对象的序列化委托回主marshaller。 The main advantage of this (apart from avoiding complicated workarounds) is that you can still take advantage of other type adaptors and custom serializers that might have been registered in the main context. 这个的主要优点(除了避免复杂的解决方法)是您仍然可以利用可能已在主上下文中注册的其他类型适配器和自定义序列化程序。 Note that registration of serializers and adapters use the exact same code: 请注意,序列化程序和适配器的注册使用完全相同的代码:

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

If you find that you need to stick with an adapter, then you can use an embedded Gson proxy to serialize the Pair properties for you, with the disadvantage that you lose access to custom registrations that you made on the parent Gson proxy: 如果您发现需要使用适配器,那么您可以使用嵌入式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();
    }
}

actually that seemed to work - getting the adapter for object - using the typeadaptorfactory to discover a "json" method on an object, and having that store away the adaptor object. 实际上似乎工作 - 获取对象的适配器 - 使用typeadaptorfactory发现对象上的“json”方法,并让该存储远离适配器对象。 Seems astonishingly complex for what is such an obvious use case? 对于这样一个明显的用例来说,似乎非常复杂吗?

eg: 例如:

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

does anyone know a better way to do it? 有谁知道更好的方法吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 TypeAdapter 的对象中一个变量(多个)的 Gson 自定义序列化器 - Gson custom seralizer for one variable (of many) in an object using TypeAdapter Gson自定义TypeAdapter列表未调用 - Gson Custom TypeAdapter for List Not Called 使用gson TypeAdapter将嵌套的JSON转换为嵌套的Java对象 - Convert nested JSON to nested Java object using gson TypeAdapter 使用 gson 为 WebClient 设置自定义编码器/解码器或 typeAdapter - set custom encoder/decoder or typeAdapter for WebClient using gson 为 Google GSON 添加自定义 TypeAdapterFactory 以检测使用注解动态返回自定义 TypeAdapter - Adding a custom TypeAdapterFactory for Google GSON to detect use of annotations to return custom TypeAdapter dynamically 如何在 Retrofit 中使用 Gson 注册自定义 TypeAdapter 或 JsonDeserializer? - How to register custom TypeAdapter or JsonDeserializer with Gson in Retrofit? 如何将Gson TypeAdapter与Mockito嘲笑的对象一起使用? - How to use Gson TypeAdapter with an object mocked by Mockito? 使用GSON和TypeAdapter将BSON(mongoDB)读入POJO - Read BSON (mongoDB) into POJO using GSON and TypeAdapter 为什么GSON在自定义TypeAdapter上为枚举生成不同的JSON? - Why does GSON produce different JSON for enum at custom TypeAdapter? Gson TypeAdapter和serializeNulls - Gson TypeAdapter and serializeNulls
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM