我有一个以JSON格式的树对象,我试图与Gson进行挑选。每个节点都包含其子节点作为对象类型节点的字段。节点是一个接口,它具有多个具体类实现。在挑选过程中,如果我不知道该节点属于哪种类型?每个节点都有一个指定类型的成员字段。当对象以序列化形式为单位并以某种方式将类型传达给GSON时,有没有办法访问该字段?

谢谢!

有帮助吗?

解决方案

我建议添加自定义 jsondeserializer 为了 NodeS:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(Node.class, new NodeDeserializer())
    .create();

您将能够访问 JsonElement 代表Deserializer方法中的节点,将其转换为 JsonObject, 并检索指定类型的字段。然后,您可以创建一个正确类型的实例 Node 基于此。

其他提示

您将需要注册Jsonserializer和Jsondeserializer。另外,您可以通过以下方式为所有接口实现通用适配器:

  • 在序列化过程中:添加实际IMPS类型的元INFO。
  • 在挑选过程中:检索该元信息并致电该类别的jsondeserailize

这是我为自己使用的实现,而且工作正常。

public class PropertyBasedInterfaceMarshal implements
        JsonSerializer<Object>, JsonDeserializer<Object> {

    private static final String CLASS_META_KEY = "CLASS_META_KEY";

    @Override
    public Object deserialize(JsonElement jsonElement, Type type,
            JsonDeserializationContext jsonDeserializationContext)
            throws JsonParseException {
        JsonObject jsonObj = jsonElement.getAsJsonObject();
        String className = jsonObj.get(CLASS_META_KEY).getAsString();
        try {
            Class<?> clz = Class.forName(className);
            return jsonDeserializationContext.deserialize(jsonElement, clz);
        } catch (ClassNotFoundException e) {
            throw new JsonParseException(e);
        }
    }

    @Override
    public JsonElement serialize(Object object, Type type,
            JsonSerializationContext jsonSerializationContext) {
        JsonElement jsonEle = jsonSerializationContext.serialize(object, object.getClass());
        jsonEle.getAsJsonObject().addProperty(CLASS_META_KEY,
                object.getClass().getCanonicalName());
        return jsonEle;
    }

}

然后,您可以为所有接口注册此适配器,如下

Gson gson = new GsonBuilder()
        .registerTypeAdapter(IInterfaceOne.class,
                new PropertyBasedInterfaceMarshal())
        .registerTypeAdapter(IInterfaceTwo.class,
                new PropertyBasedInterfaceMarshal()).create();

据我所知,这对非收集类型不起作用,或者更具体地说,是混凝土类型用于序列化的情况,并且接口类型用于应对序列化。也就是说,如果您有一个简单的类实现接口并序列化混凝土类,然后指定界面以进行挑选,则最终会处于无法恢复的情况下。

在上面的示例中,类型适配器针对接口进行了注册,但是当您使用混凝土类序列化时,将不会使用它,这意味着将永远不会设置Class_Meta_key数据。

如果将适配器指定为层次适配器(从而告诉GSON将其用于层次结构中的所有类型),则您最终会进入无限循环,因为序列化器只会继续呼吁自己。

任何人都知道如何从接口的具体实现中序列化,然后仅使用接口和InstanceCreator进行序列化?

默认情况下,Gson似乎会创建具体实例,但未设置其字段。

问题在这里记录:

http://code.google.com/p/google-gleson/issues/detail?id=411&q = interface

你必须使用 TypeToken Google Gson的课程。您当然需要一个通用的T类来使其有效

Type fooType = new TypeToken<Foo<Bar>>() {}.getType();

gson.tojson(foo,footype);

gson.fromJson(json, fooType);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top