假设我们有这个 JSON:
[
{
"__typename": "Car",
"id": "123",
"name": "Toyota Prius",
"numDoors": 4
},
{
"__typename": "Boat",
"id": "4567",
"name": "U.S.S. Constitution",
"propulsion": "SAIL"
}
]
(列表中可能还有更多元素;这仅显示了两个)
我有Car
和Boat
POJO 使用Vehicle
公共字段的基类:
public abstract class Vehicle {
public final String id;
public final String name;
}
public class Car extends Vehicle {
public final Integer numDoors;
}
public class Boat extends Vehicle {
public final String propulsion;
}
解析这个 JSON 的结果应该是一个List<Vehicle>
. 问题是没有 JSON 解析器会开箱即用地知道__typename
如何区分 aBoat
和 a Car
。
使用 Gson,我可以创建一个JsonDeserializer<Vehicle>
可以检查__typename
字段,确定这是 aCar
还是Boat
,然后使用deserialize()
提供JsonDeserializationContext
的将特定 JSON 对象解析为适当的类型。这工作正常。
但是,我正在构建的特定东西应该支持可插入的 JSON 解析器,我想我会尝试将 Moshi 作为替代解析器。但是,目前 Moshi 文档中没有很好地涵盖这个特殊问题,我很难弄清楚如何最好地解决它。
最接近的类似物JsonDeserializer<T>
是JsonAdapter<T>
. 但是,fromJson()
通过 a JsonReader
,它具有破坏性 API。要找出它是什么__typename
,我必须能够从JsonReader
事件中手动解析所有内容。当我知道正确的具体类型后,我可以调用adapter()
实例Moshi
来尝试调用现有的 Moshi 解析逻辑,但我将消耗来自 的数据JsonReader
并破坏其提供完整对象描述的能力。
另一个类似物JsonDeserializer<Vehicle>
是一个带@FromJson
注释的方法,它返回一个Vehicle
. 但是,我无法确定要传递给该方法的简单事物。我唯一能想到的就是创建另一个 POJO 来表示所有可能字段的联合:
public class SemiParsedKindOfVehicle {
public final String id;
public final String name;
public final Integer numDoors;
public final String propulsion;
public final String __typename;
}
然后,理论上,如果我有@FromJson Vehicle rideLikeTheWind(SemiParsedKindOfVehicle rawVehicle)
一个注册为类型适配器的类Moshi
,Moshi 可能能够将我的 JSON 对象解析为SemiParsedKindOfVehicle
实例并调用rideLikeTheWind()
. 在那里,我会查找__typename
,识别类型,并完全构建Car
orBoat
我自己,返回该对象。
虽然可行,但这比 Gson 方法复杂得多,而且我的Car
/Boat
场景是我需要处理的可能数据结构的简单端。
是否有另一种方法来处理我缺少的 Moshi?