从JSON确定Object的类型并使用GSON创建对象

v1s*_*hnu 4 java json gson

我在我的应用程序中使用Gson,我有几个Java对象,我通过使用GSON将它转换为JSON来呈现给前端.我知道如何使用gson将JSON转换回Java对象.

我有这个用例:当我向GSON提供一个特定的JSON字符串时,我希望它找到从中获取JSON字符串的对象的类型,并给我一个该类型的对象.

使用GSON,只有在fromJson方法中传递Object类时才能返回对象.但无论如何我可以自己gson决定吗?我无法控制另一方生成的对象.

例:

Person person = new Person();
SomeRandomObject obj = new SomeRandomObject();

String personJson = gson.toJson(person);
String anotherJson = gson.toJson(obj);
Run Code Online (Sandbox Code Playgroud)

现在如果我想将它转换回对象,我使用这个:

Person p = gson.fromJson(personJson,Person.class);
Run Code Online (Sandbox Code Playgroud)

但无论如何,我可以得到这样的对象:

Object object = gson.fromJson(anotherJson,*TheCorrespondingObject.class*)
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过尝试使用GSON抛出异常的不同对象的JSON字符串来实现这一点,但我不认为这是正确的方法.

dur*_*597 6

最好的,最容易做到这一点的方法是包裹JSON本身包含类型的容器.

例如:

{
  "foo":"bar"
}
Run Code Online (Sandbox Code Playgroud)

{
  "type":"FooContainer"
  "value": {
     "foo":"bar"
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,你说你不能这样做,所以我不会详细介绍如何实际进行反序列化.如果你可以做这个有限的改变,你可以编写一个TypeAdapterFactory让Gson完成所有其余的工作,方法是使用方法中的传递Gson对象create()并调用gson.fromJson()read方法,这将比下面的方法少得多.


想想这里真正需要发生什么.不知何故,您需要检测Websphere MQ对象中的数据并使用它来计算出来.以这种方式检测它将采用代码,分析您收到的数据,并吐出正确的对象.

你要面临的第一个问题是,你希望这样做:

Object myObj = gson.fromJson(jsonString, Object.class);
Run Code Online (Sandbox Code Playgroud)

这意味着您将覆盖默认的基本反序列化程序,它可能具有各种令人讨厌的副作用.最好将行为包装在TypeAdapter某种自定义对象中:

public class Wrapper {
  public Object data; // Encapsulate this if you want, this is just for brevity
}
Run Code Online (Sandbox Code Playgroud)

我会把铸造/仿制品留给你.有很多方法可以做到,但我建议将访问者模式作为一个不错的选择,或者创建枚举类型对象.如果你可以让所有收到的对象类型实现某种界面以使这更容易,那将是最好的,但同样,这不是你的主要问题.

您的主要问题实际上是在代码中检测这些类.现在我们有了一个包装类,我们可以使用它:

Wrapper myWrapper = gson.fromJson(jsonString, Wrapper.class);
Run Code Online (Sandbox Code Playgroud)

现在,每个生成的类都是同一个类,所以Gson很高兴.但是我们在哪里制定规则?他们进入你的习惯TypeAdapter:

public class WrapperTypeAdapter extends TypeAdapter<Wrapper> {
    @Override
    public final void write(JsonWriter out, Wrapper value) throws IOException {
        if(value == null) {
            out.nullValue();
            return;
        }

        // Don't worry about Write for now, obviously
    }

    @Override
    public final Wrapper read(JsonReader in) throws IOException {
        if(in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }

        Wrapper wrapper = new Wrapper();

        // HERE IS WHERE YOU GET TO WRITE CODE

        return wrapper;
    }
}
Run Code Online (Sandbox Code Playgroud)

在read方法中,当您流式标记时,您可以使用基于您希望JSON标记本身的规则来确定它将成为什么类,然后构造新对象.我建议将其分解为许多方法,例如MyFoo readMyFoo(JsonReader),MyBar readMyBar(JsonReader)等等.如果不了解更多有关JSON本身的内容,我很难进入更多细节,但这应该足以让你开始.