我正在使用GsonConverter
的Retrofit 2。问题是我有这样的回应:
"responseData": {
"data": "<json array>"
}
正如您所看到的,其中一个参数是JSON数组,但它是一个字符串。我应该使用TypeAdapter
并覆盖read
和write
方法吗?如果是这样,你能告诉我如何做到这一点吗?
答案 0 :(得分:0)
正如您所看到的,其中一个参数是JSON数组,但它是一个字符串。
如果响应生成器在您的控制之下,您肯定应该更改响应格式(格式良好和性能都很好(Gson不允许将字符串文字读/写为原始值)。)
我应该使用
TypeAdapter
并覆盖read
和write
方法吗?
如果无法控制服务器响应,则必须实现仅使用read
方法的自定义类型适配器。要与该响应格式保持一致,您可以定义以下自定义映射:
final class Response<T> {
final ResponseData<T> responseData = null;
}
final class ResponseData<T> {
// This is where we're telling Gson to apply the special read strategy, not to all types
@JsonAdapter(RawJsonTypeAdapterFactory.class)
final T data = null;
}
如您所见,您只需将自定义类型适配器绑定到特定字段。尽管JsonAdapter
注释也接受TypeAdapter
个类,但您无法直接绑定TypeAdapter
,因为您需要Gson
和Type
个实例。
final class RawJsonTypeAdapterFactory
implements TypeAdapterFactory {
// Gson will instantiate it itself without any issues
private RawJsonTypeAdapterFactory() {
}
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
// No additional checks here, we're assuming the necessary fields are properly annotated
final Type type = typeToken.getType();
return new TypeAdapter<T>() {
@Override
public void write(final JsonWriter out, final T value) {
throw new UnsupportedOperationException();
}
@Override
public T read(final JsonReader in)
throws IOException {
return gson.fromJson(in.nextString(), type);
}
}.nullSafe(); // And making the type adapter null-safe
}
}
现在JSON文档就像
{
"responseData": {
"data": "[1,2,3]"
}
}
可以在普通Java中轻松解析:
private static final Type intArrayResponseType = new TypeToken<Response<int[]>>() {
}.getType();
private static final Gson gson = new Gson();
...
try ( final JsonReader jsonReader = getPackageResourceJsonReader(Q43456942.class, "stringified.json") ) {
final Response<int[]> response = gson.fromJson(jsonReader, intArrayResponseType);
System.out.println(Arrays.toString(response.responseData.data));
}
输出:
[1,2,3]
您的Retrofit绑定服务可能有一个声明此方法的方法(因为Retrofit非常智能,可以将Call
参数化传递给基础Gson转换器,所以没有必要的类型标记):
Call<Response<int[]>> getIntArray();