Moshi Determine if JSON is array or single object

后端 未结 2 1570
孤街浪徒
孤街浪徒 2021-01-18 07:16

Is there a way to setup a Moshi adapter to automatically create a single Object or List based on the JSON response? Curr
2条回答
  •  生来不讨喜
    2021-01-18 07:40

    You can use a JsonQualifier to generalize this. From your example, you might use it like

    final class Foo {
      @SingleToArray final List users;
    }
    

    Here's the code with a test to demonstrate more thouroughly.

    @Retention(RUNTIME)
    @JsonQualifier public @interface SingleToArray {
      final class Adapter extends JsonAdapter> {
        final JsonAdapter> delegateAdapter;
        final JsonAdapter elementAdapter;
    
        public static final Factory FACTORY = new Factory() {
          @Nullable @Override
          public JsonAdapter create(Type type, Set annotations,
              Moshi moshi) {
            Set delegateAnnotations =
                Types.nextAnnotations(annotations, SingleToArray.class);
            if (delegateAnnotations == null) {
              return null;
            }
            if (Types.getRawType(type) != List.class) {
              throw new IllegalArgumentException(
                  "Only lists may be annotated with @SingleToArray. Found: " + type);
            }
            Type elementType = Types.collectionElementType(type, List.class);
            JsonAdapter> delegateAdapter = moshi.adapter(type, delegateAnnotations);
            JsonAdapter elementAdapter = moshi.adapter(elementType);
            return new Adapter(delegateAdapter, elementAdapter);
          }
        };
    
        Adapter(JsonAdapter> delegateAdapter, JsonAdapter elementAdapter) {
          this.delegateAdapter = delegateAdapter;
          this.elementAdapter = elementAdapter;
        }
    
        @Nullable @Override public List fromJson(JsonReader reader) throws IOException {
          if (reader.peek() != JsonReader.Token.BEGIN_ARRAY) {
            return Collections.singletonList(elementAdapter.fromJson(reader));
          }
          return delegateAdapter.fromJson(reader);
        }
    
        @Override public void toJson(JsonWriter writer, @Nullable List value)
            throws IOException {
          if (value.size() == 1) {
            elementAdapter.toJson(writer, value.get(0));
          } else {
            delegateAdapter.toJson(writer, value);
          }
        }
      }
    }
    
    @Test public void singleToArray() throws Exception {
      Moshi moshi = new Moshi.Builder().add(SingleToArray.Adapter.FACTORY).build();
      JsonAdapter> adapter =
          moshi.adapter(Types.newParameterizedType(List.class, String.class), SingleToArray.class);
      assertThat(adapter.fromJson("[\"Tom\",\"Huck\"]")).isEqualTo(Arrays.asList("Tom", "Huck"));
      assertThat(adapter.toJson(Arrays.asList("Tom", "Huck"))).isEqualTo("[\"Tom\",\"Huck\"]");
      assertThat(adapter.fromJson("\"Jim\"")).isEqualTo(Collections.singletonList("Jim"));
      assertThat(adapter.toJson(Collections.singletonList("Jim"))).isEqualTo("\"Jim\"");
      assertThat(adapter.fromJson("[]")).isEqualTo(Collections.emptyList());
      assertThat(adapter.toJson(Collections.emptyList())).isEqualTo("[]");
    }
    
        

    提交回复
    热议问题