【问题标题】:How can I use auto-value-gson to map unknown json fields如何使用 auto-value-gson 映射未知的 json 字段
【发布时间】:2018-10-05 17:48:56
【问题描述】:

我正在 android 中制作一个简单的 github gist view 应用程序,与他们的api 对话。

但我不确定如何使用 AutoValue 和 GSON 来映射此 json 响应。请注意,我已经删除了很多键,因为我目前不需要它,实际 回复看起来像this

示例响应

[
  {
    "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
      }
    }
  }
]

问题 我读过我可以在StringFile 对象之间进行映射以使其工作。但它不起作用,因为files 键是或可以是对象的对象。

那么如何使用 auto-value-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);
    }
}

相关主题和信息:

【问题讨论】:

    标签: java android gson retrofit auto-value


    【解决方案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);
        }
    
    }
    

    现在可以解析它了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-17
      • 2019-03-02
      相关资源
      最近更新 更多