30
loading...
This website collects cookies to deliver better user experience
{
"article": {
"title": "Hello world",
"body": [{
"type": "text",
"text": "Hi there"
}, {
"type": "image",
"source": "https://example.com/hello-world-banner.jpg",
"author": "John Doe",
"description": "Hello World! banner"
}, {
"type": "video",
"source": "http://mirrorblender.top-ix.org/peach/bigbuckbunny_movies/big_buck_bunny_1080p_surround.avi",
"thumbnail": "https://peach.blender.org/wp-content/uploads/dl_1080p.jpg",
"title": "Big Buck Bunny",
"duration": 574
}
]
}
}
body
array contain a field called type
, which determines the type of object being returned. This will give you flexibility to parse the objects into their own respected models, which in this case should be “text
”, “image
” and “video
”. See the 3 model examples below using Google’s AutoValue.public interface Block {
}
@AutoValue
public abstract class TextBlock implements Block {
@SerializedName("text")
public abstract String text();
}
@AutoValue
public abstract class ImageBlock implements Block {
@SerializedName("source")
public abstract String source();
@Nullable
@SerializedName("author")
public abstract String author();
@Nullable
@SerializedName("description")
public abstract String description();
}
@AutoValue
public abstract class VideoBlock implements Block {
@SerializedName("source")
public abstract String source();
@SerializedName("thumbnail")
public abstract String thumbnail();
@SerializedName("title")
public abstract String title();
@SerializedName("duration")
public abstract int duration();
}
List<Block>
return type. If you take a look at the Blocks example code, you’ll see these all implement the Block interface. This way we can easily define new typed objects we want to support in future updates.@AutoValue
public abstract class Article {
@SerializedName("title")
public abstract String title();
@SerializedName("blocks")
public abstract List<Block> blocks();
}
RuntimeTypeAdapterFactory<Block> articleBlockFactory = RuntimeTypeAdapterFactory.of(Block.class, "type")
.registerSubtype(TextBlock.class, "text")
.registerSubtype(ImageBlock.class, "image")
.registerSubtype(VideoBlock.class, "video");
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.registerTypeAdapterFactory(AutoValueTypeAdapterFactory.create())
.registerTypeAdapterFactory(articleBlockFactory)
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Block
the adapter will check if it can parse to any of the defined subtypes. If your API defines the type in a different field than "type"
you can provide it. "type"
is the default name for the key so you can omit it entirely if your API does work this way.null
instead if you don’t like this approach"type"
field will not be returned to the model — if you want this info, you’ll need to re-add it