我有一堆模型类,它们有List<X>
类型的字段,其中X
是许多类型中的一种(例如String
、Integer
,但也有我自己的一些类型)。
我的问题是,我正在处理的服务器(这超出了我的控制范围)不知何故删除了单例数组,并用包含的对象替换了它们。
例如,不返回:
{
"foo": [ "bar"],
"bleh": [ { "some": "object" } ]
}
它会传回:
{
"foo": "bar",
"bleh": { "some": "object" }
}
现在假设Java模型类看起来像这样:
public class Model {
private List<String> foo;
private List<SomeObject> bleh;
}
目前,这会导致GSON抛出异常,因为它在期望BEGIN_ARRAY
的地方找到了BEGIN_STRING
或BEGIN_OBJECT
。
对于数组或字符串列表,使用TypeAdapter<List<String>>
可以很容易地解决这个问题。但问题是,我有许多不同元素类型的List
,我不想为每种情况编写单独的TypeAdapter
。我也不能编写通用的TypeAdapter<List<?>>
。因为在某些情况下您需要知道类型。那么有没有其他方法可以将GSON配置得足够智能,只是“假装”[
和]
在它希望找到它们的地方,尽管它们并不在那里?
5条答案
按热度按时间mtb9vblg1#
但问题是我有很多不同元素类型的List,我不想为每种情况编写一个单独的TypeAdapter,也不能编写一个通用的TypeAdapter〉,因为在某些时候你需要知道类型。
这就是适配器工厂的设计用途:您可以在
Gson
示例配置中控制每种类型。现在你只需要告诉Gson * 哪些 * 字段不是格式良好的。当然,你可以配置整个
Gson
示例来接受这样的列表,但是让它使用@JsonAdapter
注解来更精确一些:试验数据:
单个. json
列表. json
示例:
而输出:
模型{foo=[bar],bleh=[某个对象{某个='对象'}]}
模型{foo=[bar],bleh=[某个对象{某个='对象'}]}
xu3bshqb2#
您可以简单地编写自己的JsonDeserializer,在其中检查您的
bleh
或foo
是JsonObjects还是JsonArrays。要检查JsonElement是数组还是对象,请执行以下操作:
oxalkeyp3#
当使用GSON库时,您可以检查下面的标记是对象还是数组。这当然要求您在解析XML时更细粒度,但它允许您完全控制您想从它得到什么。有时我们无法控制XML,它可能很方便。
下面是一个使用
JsonReader
类解析文件以检查下一个标记是对象还是数组的示例:在数组/对象的末尾,你可以做同样的事情,但是对于结尾标记:
这样,您就可以使用相同的代码(添加一个额外的检查,以验证您是在数组上还是在对象上)来分析对象数组或单个对象。
8xiog9wr4#
我在使用一个供应商的xml / json时也遇到了同样的问题--他们肯定不会为我修改他们的代码:)在修改之前,我使用了网上的几个资源来适应我自己的This SO answer was very helpful版本。我花了一些时间查看gson代码,发现了很多我想要访问的私有变量。所以,本质上,我的自定义集合适配器所做的就是查看下一个元素是否是对象。如果不是,我们就把读取委托给上一个适配器(我们已经覆盖了)。
如果下一个元素是一个对象,我们使用gson来处理它。然后我们将它转换成一个对象的数组。使用gson将它写入一个字符串,然后将该字符串作为一个JsonReader传递给底层适配器。然后,这可以创建底层列表的一个示例,并添加我们拥有的一个元素。
下面是适配器类型工厂:
那么我拥有的类型适配器是:
最后,我们需要注册适配器工厂:
到目前为止,它似乎在处理单个和多个对象方面都工作得很好--尽管如果它需要一些调整,我也不会感到惊讶。
gstyhher5#
一种解决方案是编写一个定制的
TypeAdapterFactory
,它创建一个适配器来查看JSON数据。如果遇到JSON数组以外的数据(或JSON空值),它会在反序列化之前将其 Package 在JSON数组中:上述实现仅设计用于字段上的
@JsonAdapter
,例如:与currently accepted answer相比,这提供了以下优点,因为它只是将实际的反序列化委托给
listAdapterDelegate
:List
(或Collection
)子类,因为它们的创建已委托给Gson但它也有以下缺点:
JsonElement