Moshi 通用类型适配器

Posted

技术标签:

【中文标题】Moshi 通用类型适配器【英文标题】:Moshi generic type adapter 【发布时间】:2018-02-21 22:01:58 【问题描述】:

假设有以下代表服务器响应的参数化数据类:

public class SocketResponse<T> 
    private String responseMessage;
    private int responseCode;
    private T entity;

我知道在运行时 T 将是什么类型。 moshi 是否像 Gson 一样支持泛型类型适配器?使用 Gson id 执行以下操作来解析它。

Type typeA = new TypeToken<SocketResponse<MyResponseA>>().getType();
SocketResponse<MyResponseA> responseA = getResponse("json", typeA);

Type typeB = new TypeToken<SocketResponse<MyResponseB>>().getType();
SocketResponse<MyResponseB> responseB = getResponse("json", typeB);


private String getResponse(Type t)
    return gson.fromJson(response, type);

【问题讨论】:

【参考方案1】:

与 Gson 的 TypeToken API 相比,Moshi 使用 Types 上的工厂方法来获取 Java 类型。

Type typeA = Types.newParameterizedType(SocketResponse.class, MyResponseA.class);
JsonAdapter<SocketResponse<MyResponseA>> adapter = moshi.adapter(typeA);

然后,使用 JsonAdapter 对你的类型进行反序列化和序列化,就像 Gson 的 TypeAdapter 一样。

【讨论】:

【参考方案2】:

我主要使用 GSON,但也许是这样的?

Type type = Types.newParameterizedType(SocketResponse.class, Object.class);
JsonAdapter<SocketResponse<?>> jsonAdapter = moshi.adapter(type);

【讨论】:

差不多,但是示例问题中的参数是MyResponseA或MyResponseB(不是Object)。【参考方案3】:

仅针对更复杂的情况,如果T 等于像List&lt;MyResponseA&gt; 这样的泛型类型。例如,您可以这样做(在kotlin):

val t = Types.newParameterizedType(
    SocketResponse::class.java, Types.newParameterizedType(
        List::class.java,
        MyResponseA::class.java
    )
)
val adapter = moshi.adapter<SocketResponse<List<MyResponseA>>>(t)

【讨论】:

以上是关于Moshi 通用类型适配器的主要内容,如果未能解决你的问题,请参考以下文章

Moshi 适配器跳过 List<T> 中的坏对象

如何在 moshi (kotlin) 中解析 LinkedHashMap

自定义呼叫适配器改造中的通用类型

如果我有消息类型列表,如何在 MassTransit 中注册通用消费者适配器

制作一个类型精美的通用事件到处理程序分配器函数

容器适配器(adapter)