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

时间:2015-08-10 13:45:42

标签: 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);

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

Person p = gson.fromJson(personJson,Person.class);

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

Object object = gson.fromJson(anotherJson,*TheCorrespondingObject.class*)

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

3 个答案:

答案 0 :(得分:6)

最好,最简单的方法是将JSON本身包装在包含该类型的容器中。

例如:

{
  "foo":"bar"
}

变为

{
  "type":"FooContainer"
  "value": {
     "foo":"bar"
  }
}

但是,你说你不能这样做,所以我不会详细介绍如何实际进行反序列化。如果您可以执行此有限更改,则可以使用{{1中的传递的Gson对象编写TypeAdapterFactory并让Gson执行所有其余工作方法并在read方法中调用create(),这将比下面的方法少得多。

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

您将面临的第一个问题是想要这样做:

gson.fromJson()

这意味着您将覆盖默认的基本反序列化程序,它可能具有各种令人讨厌的副作用。对于某种自定义对象,最好将行为包装在Object myObj = gson.fromJson(jsonString, Object.class); 中:

TypeAdapter

我会把演员/仿制品留给你。有很多方法可以做到,但我建议将Visitor Pattern作为一个不错的选择,或者创建一个enum type object。如果你可以让所有收到的对象类型实现某种界面以使这更容易,那将是最好的,但是,这不是你的主要问题。

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

public class Wrapper {
  public Object data; // Encapsulate this if you want, this is just for brevity
}

现在,每个生成的类都是同一个类,所以Gson很高兴。但是我们在哪里制定规则?他们会使用您的自定义TypeAdapter

Wrapper myWrapper = gson.fromJson(jsonString, Wrapper.class);

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

答案 1 :(得分:0)

通用答案:您必须在生成的JSON中添加一些内容以指示它是从哪个生成的。

说,而不是

{
    "name": "John"
}

你会产生类似的东西:

{
    "type": "Customer"
    "name": "John"
}

如何在GSON中执行此操作留给读者练习。 ;)

编辑:哦,你不能篡改JSON。没关系,那么。

但是,如果没有某种标识符,很难以通用方式执行此操作,特别是考虑到某些类可能恰好具有完全相同的字段。

答案 2 :(得分:0)

通过分析原始字符串手动:

var x = 100
x = x%1000

或者您可以使用JSON Simple并读取任何JSON