使用 Moshi 反序列化时丢失字段值 JsonAdapter.Factory
Losing field values when deserializing with Moshi JsonAdapter.Factory
我不确定哪里出错了。
我的简单模型如下:
final class Data {
final int num;
Data(int num) {
this.num = num;
}
static final class Wrapper {
final List<Data> data;
final long meta;
Wrapper(List<Data> data, long meta) {
this.data = data;
this.meta = meta;
}
}
}
我的工厂从 Wrapper
中取出 Data
:
final class ObjectAsListJsonAdapterFactory implements JsonAdapter.Factory {
@Override public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
if (!List.class.isAssignableFrom(Types.getRawType(type))) {
return null;
}
JsonAdapter<List<Object>> listDelegate = moshi.nextAdapter(this, type, annotations);
Type innerType = Types.collectionElementType(type, List.class);
JsonAdapter<Object> objectDelegate = moshi.adapter(innerType, annotations);
return new ListJsonAdapter<>(listDelegate, objectDelegate);
}
static final class ListJsonAdapter<T> extends JsonAdapter<List<T>> {
private final JsonAdapter<List<T>> listDelegate;
private final JsonAdapter<T> objectDelegate;
ListJsonAdapter(JsonAdapter<List<T>> listDelegate, JsonAdapter<T> objectDelegate) {
this.listDelegate = listDelegate;
this.objectDelegate = objectDelegate;
}
@Override public List<T> fromJson(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonReader.Token.BEGIN_OBJECT) {
return Collections.singletonList(objectDelegate.fromJson(jsonReader));
} else {
return listDelegate.fromJson(jsonReader);
}
}
@Override public void toJson(JsonWriter jsonWriter, List<T> list) throws IOException {
listDelegate.toJson(jsonWriter, list);
}
}
}
但是当我 运行:
String json = "{\n"
+ " \"data\": [\n"
+ " {\n"
+ " \"num\": 5\n"
+ " }\n"
+ " ],\n"
+ " \"meta\": 21\n"
+ "}";
Moshi moshi = new Moshi.Builder().add(new ObjectAsListJsonAdapterFactory()).build();
ParameterizedType type = Types.newParameterizedType(List.class, Data.class);
JsonAdapter<List<Data>> adapter = moshi.adapter(type);
List<Data> expected = adapter.fromJson(json);
expected
包含一个 Data
,其 num
字段的值为 0
。
我错过了什么?
该字段有其默认值,因为这不是 JSON 所需的 JsonAdapter.Factory
。该工厂正在尝试制作类似于单个数组项的对象。
这是您想要的展开方式:
static final class DataUnwrapperAdapterFactory implements JsonAdapter.Factory {
@Override
public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
if (!List.class.isAssignableFrom(Types.getRawType(type))) {
return null;
}
if (!Data.class.isAssignableFrom(Types.getRawType(Types.collectionElementType(type, List.class)))) {
return null;
}
JsonAdapter<List<Data>> listDelegate = moshi.nextAdapter(this, type, annotations);
JsonAdapter<Data.Wrapper> wrapperDelegate = moshi.adapter(Data.Wrapper.class, annotations);
return new DataUnwrapperAdapter(listDelegate, wrapperDelegate);
}
static final class DataUnwrapperAdapter extends JsonAdapter<List<Data>> {
private final JsonAdapter<List<Data>> listDelegate;
private final JsonAdapter<Data.Wrapper> wrapperDelegate;
DataUnwrapperAdapter(JsonAdapter<List<Data>> listDelegate,
JsonAdapter<Data.Wrapper> wrapperDelegate) {
this.listDelegate = listDelegate;
this.wrapperDelegate = wrapperDelegate;
}
@Override public List<Data> fromJson(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonReader.Token.BEGIN_OBJECT) {
Data.Wrapper wrapper = wrapperDelegate.fromJson(jsonReader);
return wrapper.data;
} else {
return listDelegate.fromJson(jsonReader);
}
}
@Override public void toJson(JsonWriter jsonWriter, List<Data> list) throws IOException {
listDelegate.toJson(jsonWriter, list);
}
}
}
现在,您可以执行以下操作:
String json = "{\n"
+ " \"other_garbage\": \"hiya\",\n"
+ " \"data\": [\n"
+ " {\n"
+ " \"num\": 5\n"
+ " }\n"
+ " ],\n"
+ " \"meta\": 21\n"
+ "}";
Moshi moshi = new Moshi.Builder().add(new DataUnwrapperAdapterFactory()).build();
ParameterizedType type = Types.newParameterizedType(List.class, Data.class);
JsonAdapter<List<Data>> adapter = moshi.adapter(type);
List<Data> expected = adapter.fromJson(json);
非常感谢(一如既往)Jake 和 Jesse 找到了这个解决方案。
我不确定哪里出错了。
我的简单模型如下:
final class Data {
final int num;
Data(int num) {
this.num = num;
}
static final class Wrapper {
final List<Data> data;
final long meta;
Wrapper(List<Data> data, long meta) {
this.data = data;
this.meta = meta;
}
}
}
我的工厂从 Wrapper
中取出 Data
:
final class ObjectAsListJsonAdapterFactory implements JsonAdapter.Factory {
@Override public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
if (!List.class.isAssignableFrom(Types.getRawType(type))) {
return null;
}
JsonAdapter<List<Object>> listDelegate = moshi.nextAdapter(this, type, annotations);
Type innerType = Types.collectionElementType(type, List.class);
JsonAdapter<Object> objectDelegate = moshi.adapter(innerType, annotations);
return new ListJsonAdapter<>(listDelegate, objectDelegate);
}
static final class ListJsonAdapter<T> extends JsonAdapter<List<T>> {
private final JsonAdapter<List<T>> listDelegate;
private final JsonAdapter<T> objectDelegate;
ListJsonAdapter(JsonAdapter<List<T>> listDelegate, JsonAdapter<T> objectDelegate) {
this.listDelegate = listDelegate;
this.objectDelegate = objectDelegate;
}
@Override public List<T> fromJson(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonReader.Token.BEGIN_OBJECT) {
return Collections.singletonList(objectDelegate.fromJson(jsonReader));
} else {
return listDelegate.fromJson(jsonReader);
}
}
@Override public void toJson(JsonWriter jsonWriter, List<T> list) throws IOException {
listDelegate.toJson(jsonWriter, list);
}
}
}
但是当我 运行:
String json = "{\n"
+ " \"data\": [\n"
+ " {\n"
+ " \"num\": 5\n"
+ " }\n"
+ " ],\n"
+ " \"meta\": 21\n"
+ "}";
Moshi moshi = new Moshi.Builder().add(new ObjectAsListJsonAdapterFactory()).build();
ParameterizedType type = Types.newParameterizedType(List.class, Data.class);
JsonAdapter<List<Data>> adapter = moshi.adapter(type);
List<Data> expected = adapter.fromJson(json);
expected
包含一个 Data
,其 num
字段的值为 0
。
我错过了什么?
该字段有其默认值,因为这不是 JSON 所需的 JsonAdapter.Factory
。该工厂正在尝试制作类似于单个数组项的对象。
这是您想要的展开方式:
static final class DataUnwrapperAdapterFactory implements JsonAdapter.Factory {
@Override
public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
if (!List.class.isAssignableFrom(Types.getRawType(type))) {
return null;
}
if (!Data.class.isAssignableFrom(Types.getRawType(Types.collectionElementType(type, List.class)))) {
return null;
}
JsonAdapter<List<Data>> listDelegate = moshi.nextAdapter(this, type, annotations);
JsonAdapter<Data.Wrapper> wrapperDelegate = moshi.adapter(Data.Wrapper.class, annotations);
return new DataUnwrapperAdapter(listDelegate, wrapperDelegate);
}
static final class DataUnwrapperAdapter extends JsonAdapter<List<Data>> {
private final JsonAdapter<List<Data>> listDelegate;
private final JsonAdapter<Data.Wrapper> wrapperDelegate;
DataUnwrapperAdapter(JsonAdapter<List<Data>> listDelegate,
JsonAdapter<Data.Wrapper> wrapperDelegate) {
this.listDelegate = listDelegate;
this.wrapperDelegate = wrapperDelegate;
}
@Override public List<Data> fromJson(JsonReader jsonReader) throws IOException {
if (jsonReader.peek() == JsonReader.Token.BEGIN_OBJECT) {
Data.Wrapper wrapper = wrapperDelegate.fromJson(jsonReader);
return wrapper.data;
} else {
return listDelegate.fromJson(jsonReader);
}
}
@Override public void toJson(JsonWriter jsonWriter, List<Data> list) throws IOException {
listDelegate.toJson(jsonWriter, list);
}
}
}
现在,您可以执行以下操作:
String json = "{\n"
+ " \"other_garbage\": \"hiya\",\n"
+ " \"data\": [\n"
+ " {\n"
+ " \"num\": 5\n"
+ " }\n"
+ " ],\n"
+ " \"meta\": 21\n"
+ "}";
Moshi moshi = new Moshi.Builder().add(new DataUnwrapperAdapterFactory()).build();
ParameterizedType type = Types.newParameterizedType(List.class, Data.class);
JsonAdapter<List<Data>> adapter = moshi.adapter(type);
List<Data> expected = adapter.fromJson(json);
非常感谢(一如既往)Jake 和 Jesse 找到了这个解决方案。