gpt4 book ai didi

moshi - 如何使用 Moshi 反序列化泛型类型?

转载 作者:行者123 更新时间:2023-12-04 03:36:23 28 4
gpt4 key购买 nike

假设我们有这个 JSON:

[
{
"__typename": "Car",
"id": "123",
"name": "Toyota Prius",
"numDoors": 4
},
{
"__typename": "Boat",
"id": "4567",
"name": "U.S.S. Constitution",
"propulsion": "SAIL"
}
]

(列表中可能还有更多元素;这仅显示了两个)

我有 CarBoat POJO,它们对公共(public)字段使用 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 是如何区分 BoatCar 的。

使用 Gson,我可以创建一个 JsonDeserializer<Vehicle> 来检查 __typename 字段,确定这是 Car 还是 Boat ,然后在提供的 deserialize() 上使用 JsonDeserializationContext 将特定的 JSON 对象解析为适当的类型。这工作正常。

但是,我正在构建的特定东西应该支持可插入的 JSON 解析器,我想我会尝试将 Moshi 作为替代解析器。但是,目前 Moshi 文档中并没有很好地涵盖这个特殊问题,我很难弄清楚如何最好地解决它。

最接近 JsonDeserializer<T> is JsonAdapter<T> 的类似物。然而, fromJson() 被传递了一个 JsonReader ,它有一个破坏性的 API。要找出 __typename 是什么,我必须能够从 JsonReader 事件中手动解析所有内容。一旦我知道正确的具体类型,我可以调用 adapter() on the Moshi instance 来尝试调用现有的 Moshi 解析逻辑,但我将消耗 JsonReader 中的数据并破坏其提供完整对象描述的能力。
JsonDeserializer<Vehicle> 的另一个类似物是返回 @FromJson Vehicle -annotated method 。但是,我无法确定要传递给该方法的简单事物。我唯一能想到的就是创建另一个 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 ,识别类型,然后自己完全构建 CarBoat,返回该对象。

虽然可行,但这比 Gson 方法复杂得多,而且我的 Car/ Boat 场景是我需要处理的可能数据结构的简单端。

是否有另一种方法来处理我缺少的 Moshi?

最佳答案

moshi-adapters附加库包含 a PolymorphicJsonAdapterFactory class .虽然这个库的 JavaDocs 似乎没有发布,但源代码确实包含了它的使用的详细描述。
我的问题中示例的设置是:

  private val moshi = Moshi.Builder()
.add(
PolymorphicJsonAdapterFactory.of(Vehicle::class.java, "__typename")
.withSubtype(Car::class.java, "Car")
.withSubtype(Boat::class.java, "Boat")
)
.build()
现在,我们的 Moshi对象知道如何转换像 List<Vehicle> 这样的东西到/从 JSON,基于 __typename JSON 中的属性,将其与 "Car" 进行比较和 "Boat"创建 CarBoat类,分别。

关于moshi - 如何使用 Moshi 反序列化泛型类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40950240/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com