Gson定制序列化 [英] Gson custom serialization

查看:86
本文介绍了Gson定制序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望有一个自定义的GSON反序列化器,以便每当它反序列化JSON对象(即大括号{ ... }中的任何内容)时,它将查找$type节点并使用其内置的反序列化功能对该类型进行反序列化.如果未找到$type对象,则它会像平常一样执行操作.

I wish to have a custom GSON deserializer such that whenever it is deserializing a JSON object (i.e. anything within curly brackets { ... }), it will look for a $type node and deserialize using its inbuilt deserializing capability to that type. If no $type object is found, it just does what it normal does.

因此,例如,我希望它可以工作:

So for example, I would want this to work:

{
    "$type": "my.package.CustomMessage"
    "payload" : {
        "$type": "my.package.PayloadMessage",
        "key": "value"
    }
}

public class CustomMessage {

    public Object payload;
}

public class PayloadMessage implements Payload {

    public String key;
}

致电:Object customMessage = gson.fromJson(jsonString, Object.class).

所以目前,如果我将payload类型更改为Payload界面:

So currently if I change the payload type to the Payload interface:

public class CustomMessage {

    public Payload payload;
}

然后以下TypeAdapaterFactory将执行我想要的操作:

Then the following TypeAdapaterFactory will do what I want:

final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
final PojoTypeAdapter thisAdapter = this;

public T read(JsonReader reader) throws IOException {

    JsonElement jsonElement = (JsonElement)elementAdapter.read(reader);

    if (!jsonElement.isJsonObject()) {
        return delegate.fromJsonTree(jsonElement);
    }

    JsonObject jsonObject = jsonElement.getAsJsonObject();
    JsonElement typeElement = jsonObject.get("$type");

    if (typeElement == null) {
        return delegate.fromJsonTree(jsonElement);
    }

    try {
        return (T) gson.getDelegateAdapter(
                thisAdapter,
                TypeToken.get(Class.forName(typeElement.getAsString()))).fromJsonTree(jsonElement);
    } catch (ClassNotFoundException ex) {
        throw new IOException(ex.getMessage());
    }
}

但是,我希望它在payload类型为Object或与此相关的任何类型时起作用,并在无法分配变量的情况下抛出某种类型匹配异常.

However, I would like it to work when payload is of type Object or any type for that matter, and throw some sort of type match exception if it can't assign the variable.

推荐答案

看着Gson的源代码,我发现了问题所在

Looking at the source for Gson, I have found what I think is the issue:

// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);

// user's type adapters
factories.addAll(typeAdapterFactories);

如您所见,ObjectTypeAdapter将优先于我的工厂.

As you can see the ObjectTypeAdapter will take precedence over my factory.

据我所知,唯一的解决方案是使用反射从列表中删除ObjectTypeAdapter或在其前面插入我的工厂.我已经做到了,而且行得通.

The only solution as far as I can see is to use reflection to remove the ObjectTypeAdapter from the list or insert my factory before it. I have done this and it works.

这篇关于Gson定制序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆