【问题标题】:Losing field values when deserializing with Moshi JsonAdapter.Factory使用 Moshi JsonAdapter.Factory 反序列化时丢失字段值
【发布时间】:2016-04-07 12:10:24
【问题描述】:

我不确定我哪里出错了。

我的简单模型如下所示:

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

我错过了什么?

【问题讨论】:

    标签: java json moshi


    【解决方案1】:

    该字段具有其默认值,因为这不是该 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 获得此解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-03
      • 2016-09-16
      • 2017-02-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-04
      • 1970-01-01
      • 2015-11-09
      相关资源
      最近更新 更多