Как я могу использовать auto-value-gson для сопоставления неизвестных полей json

Я делаю простое приложение для просмотра Gist на Android, которое общается с их api.

Но я не уверен, как я могу использовать AutoValue и GSON для сопоставления этого ответа json. Обратите внимание, что я удалил много ключей, так как они мне сейчас не нужны, фактический ответ выглядит следующим образом: этот.

Пример ответа

[
  {
    "id": "3937809cf12adae05595c43c5ef4ce56",
    "files": {
      "main.css": {
        "filename": "main.css",
        "type": "text/css",
        "language": "CSS",
        "raw_url": "https://gist.githubusercontent.com/*/3937809cf12adae05595c43c5ef4ce56/raw/f46b97a4cf561fa18e50e14bed734eea78bc58d9/main.css",
        "size": 102
      },
      "readme.txt": {
        "filename": "readme.txt",
        "type": "text/plain",
        "language": "Text",
        "raw_url": "https://gist.githubusercontent.com/*/3937809cf12adae05595c43c5ef4ce56/raw/aa7bf7046baaf58b23b4fa4c3b19a575d5eae36e/readme.txt",
        "size": 192
      }
    }
  }
]

Вопрос Я читал, что могу сопоставить объекты String и File, чтобы заставить его работать. Но это не работает, так как ключ files является или может быть объектом объектов.

Итак, как я могу сопоставить эти объекты неизвестных объектов с автоматическим значением-gson? Это вообще возможно?

Код

GistResponse.java

@AutoValue
public abstract class GistResponse {

    @SerializedName("id")
    public abstract String getId();

    @SerializedName("files")
    public abstract FileName getFileNameList();

    public static Builder builder() {
        return new AutoValue_GistResponse.Builder();
    }

    @AutoValue.Builder
    public abstract static class Builder {
        public abstract Builder setId(String value);
        public abstract Builder setFileNameList(FileName value);

        public abstract GistResponse build();
    }

    public static TypeAdapter<GistResponse> typeAdapter(Gson gson) {
        return new AutoValue_GistResponse.GsonTypeAdapter(gson);
    }

}

ИмяФайла.java

@AutoValue
public abstract class FileName {

    public abstract Map<String, File> getFilesList();

    public static Builder builder() {
        return new AutoValue_FileName.Builder();
    }

    @AutoValue.Builder
    public abstract static class Builder {
        public abstract Builder setFilesList(Map<String, File> value);
        public abstract FileName build();
    }

    public static TypeAdapter<FileName> typeAdapter(Gson gson) {
        return new AutoValue_FileName.GsonTypeAdapter(gson);
    }
}

Файл.java

@AutoValue
public abstract class File {

    @SerializedName("filename")
    public abstract String getFileName();

    @SerializedName("type")
    public abstract String getType();

    @SerializedName("language")
    public abstract String getLanguage();

    @SerializedName("raw_url")
    public abstract String getRawUrl();

    @SerializedName("size")
    public abstract Integer getSize();

    public static Builder builder() { return new AutoValue_File.Builder(); }

    @AutoValue.Builder
    public abstract static class Builder {
        public abstract Builder setFileName(String value);
        public abstract Builder setType(String value);
        public abstract Builder setLanguage(String value);
        public abstract Builder setRawUrl(String value);
        public abstract Builder setSize(Integer value);

        public abstract File build();
    }

    public static TypeAdapter<File> typeAdapter(Gson gson) {
        return new AutoValue_File.GsonTypeAdapter(gson);
    }
}

Похожие темы и информация:


person sphrak    schedule 25.04.2018    source источник


Ответы (1)


С тех пор я нашел решение, состоящее в написании пользовательского TypeAdapter, что на самом деле было довольно просто.

Вот код:

public class FileTypeAdapter extends TypeAdapter {

    @Override
    public void write(JsonWriter out, Object value) throws IOException {}

    @Override
    public List<File> read(JsonReader jsonReader) throws IOException {

        ArrayList<File> fileList = new ArrayList<>();

        if (jsonReader.peek() == JsonToken.NULL) {
            jsonReader.nextNull();
            return fileList;
        }

        jsonReader.beginObject();
        while (jsonReader.hasNext()) {

            jsonReader.nextName();

            if (jsonReader.peek() == JsonToken.NULL) {
                jsonReader.nextNull();
                continue;
            }

            File.Builder file = File.builder();

            jsonReader.beginObject();
            while (jsonReader.hasNext()) {

                String nextName = jsonReader.nextName();

                switch (nextName) {
                    case "filename": {
                        String nextString = jsonReader.nextString();
                        file.setFileName(nextString);
                        break;
                    }
                    case "type": {
                        String nextString = jsonReader.nextString();
                        file.setType(nextString);
                        break;
                    }
                    case "language": {

                        if (jsonReader.peek() == JsonToken.NULL) {
                            jsonReader.nextNull();
                        } else {
                            String nextString = jsonReader.nextString();
                            file.setLanguage(nextString);
                        }
                        break;
                    }
                    case "raw_url": {
                        String nextString = jsonReader.nextString();
                        file.setRawUrl(nextString);
                        break;
                    }
                    case "size": {
                        Integer nextInt = jsonReader.nextInt();
                        file.setSize(nextInt);
                        break;
                    }
                    default: {
                        jsonReader.skipValue();
                    }
                }
            }
            fileList.add(file.build());
            jsonReader.endObject();
        }
        jsonReader.endObject();
        return fileList;
    }
}

Затем просто аннотируйте поле файлов с помощью @GsonTypeAdapter внутри GistResponse.java.

@AutoValue
public abstract class GistResponse {

    @SerializedName("id")
    public abstract String getId();

    @GsonTypeAdapter(FileTypeAdapter.class)
    @SerializedName("files")
    public abstract FileName getFileNameList();

    public static Builder builder() {
        return new AutoValue_GistResponse.Builder();
    }

    @AutoValue.Builder
    public abstract static class Builder {
        public abstract Builder setId(String value);
        public abstract Builder setFileNameList(FileName value);

        public abstract GistResponse build();
    }

    public static TypeAdapter<GistResponse> typeAdapter(Gson gson) {
        return new AutoValue_GistResponse.GsonTypeAdapter(gson);
    }

}

И теперь его можно разобрать.

person sphrak    schedule 26.04.2018