Reputation: 539
I am making a simple github gist view app in android that talks with their api.
But I am unsure how I can use AutoValue and GSON to map this json response. Do note that I have removed alot of keys since I dont need it currently, the actual response looks like 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
}
}
}
]
Question
I have read that I could map between String
and File
object to get it to work. But it does not work since files
key is or can be an object of objects.
So how can I map these object of unknown objects with auto-value-gson? Is it even possible?
@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);
}
}
@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);
}
}
@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);
}
}
Upvotes: 1
Views: 1498
Reputation: 539
I have since found a solution which consists of writing a custom TypeAdapter
which was actually pretty easy.
Here is the code:
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;
}
}
Then just annotate the files field in with @GsonTypeAdapter
inside 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);
}
}
And now its possible to parse it.
Upvotes: 1