假设我们有这个 JSON:
[
{
"__typename": "Car",
"id": "123",
"name": "Toyota Prius",
"numDoors": 4
},
{
"__typename": "Boat",
"id": "4567",
"name": "U.S.S. Constitution",
"propulsion": "SAIL"
}
]
(列表中可能还有更多元素;这仅显示了两个)
我有Car和BoatPOJO 使用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,识别类型,并完全构建CarorBoat我自己,返回该对象。
虽然可行,但这比 Gson 方法复杂得多,而且我的Car/Boat场景是我需要处理的可能数据结构的简单端。
是否有另一种方法来处理我缺少的 Moshi?