使用 Retrofit 和 RxJava,如果 JSON 没有直接映射到模型对象,我该如何反序列化?
Using Retrofit and RxJava, how do I deserialize JSON when it doesn't map directly to a model object?
API 我正在使用 "flat" 格式的 returns 对象(及其包含的对象),但我无法使其与 Retrofit 和RxJava.
考虑 /employees/{id}
端点的这个 JSON 响应:
{
"id": "123",
"id_to_name": {
"123" : "John Doe"
},
"id_to_age": {
"123" : 30
}
}
使用 Retrofit 和 RxJava,如何将其反序列化为具有 name
和 age
字段的 Employee
对象?
理想情况下,我希望使用 Employee
对象调用 RxJava 的 onNext
方法。这可能吗?这也许可以通过某种类型的自定义反序列化器子类来完成(我目前正在使用 Gson)?
我意识到我可以创建一个直接映射到 JSON 响应的 EmployeeResponse
对象,但每次我都必须将 EmployeeResponse
映射到 Employee
对象在 activity 中使用它似乎有点不幸。当平面响应还包含其他需要反序列化并设置为 Employee
字段的对象时,它也会变得更加复杂。
有没有更好的方法?
这个问题的完整解决方案看起来很多,但这将使您可以使用 Employee
而不是 EmployeeResponse
来编写 Retrofit 接口。这是游戏计划:
- 您仍然需要
EmployeeResponse
和 Employee
对象,其中 EmployeeResponse
恰好映射到您从 API 中获得的内容。将响应视为 Employee
的构建器并编写一个静态工厂方法,该方法 return 是 EmployeeResponse
的 Employee
,即。 Employee employee = Employee.newInstance(response);
- 您将为 Gson 创建自定义
TypeAdapterFactory
。当 Gson 看到您请求一个 Employee
对象时,我们会让 TypeAdapter 实际上创建一个 EmployeeResponse
,然后 return 通过上述静态工厂方法创建 Employee
。
您的 TypeAdapterFactory 看起来像这样:
public class EmployeeAdapterFactory implements TypeAdapterFactory {
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return type.getRawType() == Employee.class
? (TypeAdapter<T>) employeeAdapter(gson, (TypeToken<Employee>) type)
: null;
}
private TypeAdapter<Employee> employeeAdapter(Gson gson, TypeToken<Employee> type) {
return new TypeAdapter<Employee>() {
@Override public void write(JsonWriter out, Employee value) throws IOException {
// TODO serialization logic to go from an Employee back to EmployeeResponse structure, if necessary
}
@Override public Employee read(JsonReader in) throws IOException {
return Employee.newInstance(gson.fromJson(in, EmployeeResponse.class));
}
};
}
}
制作Gson时注册工厂:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new EmployeeAdapterFactory())
.build();
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://foo.bar")
.addConverterFactory(GsonConverterFactory.create(gson))
... // your other Retrofit configs, like RxJava call adapter factory
.build();
现在您可以使用 Employee
而不是 EmployeeResponse
.
安全地定义所有 Retrofit 接口
API 我正在使用 "flat" 格式的 returns 对象(及其包含的对象),但我无法使其与 Retrofit 和RxJava.
考虑 /employees/{id}
端点的这个 JSON 响应:
{
"id": "123",
"id_to_name": {
"123" : "John Doe"
},
"id_to_age": {
"123" : 30
}
}
使用 Retrofit 和 RxJava,如何将其反序列化为具有 name
和 age
字段的 Employee
对象?
理想情况下,我希望使用 Employee
对象调用 RxJava 的 onNext
方法。这可能吗?这也许可以通过某种类型的自定义反序列化器子类来完成(我目前正在使用 Gson)?
我意识到我可以创建一个直接映射到 JSON 响应的 EmployeeResponse
对象,但每次我都必须将 EmployeeResponse
映射到 Employee
对象在 activity 中使用它似乎有点不幸。当平面响应还包含其他需要反序列化并设置为 Employee
字段的对象时,它也会变得更加复杂。
有没有更好的方法?
这个问题的完整解决方案看起来很多,但这将使您可以使用 Employee
而不是 EmployeeResponse
来编写 Retrofit 接口。这是游戏计划:
- 您仍然需要
EmployeeResponse
和Employee
对象,其中EmployeeResponse
恰好映射到您从 API 中获得的内容。将响应视为Employee
的构建器并编写一个静态工厂方法,该方法 return 是EmployeeResponse
的Employee
,即。Employee employee = Employee.newInstance(response);
- 您将为 Gson 创建自定义
TypeAdapterFactory
。当 Gson 看到您请求一个Employee
对象时,我们会让 TypeAdapter 实际上创建一个EmployeeResponse
,然后 return 通过上述静态工厂方法创建Employee
。
您的 TypeAdapterFactory 看起来像这样:
public class EmployeeAdapterFactory implements TypeAdapterFactory {
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return type.getRawType() == Employee.class
? (TypeAdapter<T>) employeeAdapter(gson, (TypeToken<Employee>) type)
: null;
}
private TypeAdapter<Employee> employeeAdapter(Gson gson, TypeToken<Employee> type) {
return new TypeAdapter<Employee>() {
@Override public void write(JsonWriter out, Employee value) throws IOException {
// TODO serialization logic to go from an Employee back to EmployeeResponse structure, if necessary
}
@Override public Employee read(JsonReader in) throws IOException {
return Employee.newInstance(gson.fromJson(in, EmployeeResponse.class));
}
};
}
}
制作Gson时注册工厂:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new EmployeeAdapterFactory())
.build();
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://foo.bar")
.addConverterFactory(GsonConverterFactory.create(gson))
... // your other Retrofit configs, like RxJava call adapter factory
.build();
现在您可以使用 Employee
而不是 EmployeeResponse
.