I have a client/server application that exposes data and commands through REST APIs. This API exposes a GET /recipes/:id endpoint that instructs the client on how to show a recipe. A recipe can be made of diverse activities, each of them carrying specific contextual data. Summing up, the API response would look like this
GET /recipes/xxxx
[
{
activityType: "TYPE_1",
commonData: "this",
contextualData: {
foo : "bar"
}
},
{
activityType: "TYPE_2",
commonData: "that",
contextualData: {
hello : "world"
}
},
]
of course, clients can correctly parse contextual data by inferring the data model from the "activityType" field.
Even if this apparently works fine, I still feel that it's missing the whole purpose of REST: the API is polimorphic and the correct interpretation of the result is not built in the contract but relies on a semantic rule. How the client and the server can negotiate the data type if this can be arbitrarly changed from the server: eg. what happens if a new activity type is introduced without client changes?
Last but not the least: some code generators could struggle with this type of API definition and would be difficult to generate code from API documentation
a possible solution to this would be by "splitting" the API like this
GET /recipes/xxxx
[
{
type: "TYPE_1",
commonData: "this",
contextualData: {
href : "/recipes/xxx/activities/1"
}
},
{
type: "TYPE_2",
commonData: "that",
contextualData: {
href: "/recipes/xxx/activities/2"
}
},
]
the call to "/recipes/xxx/activities/1" endpoint, for example, would have
Content-Type: application/vnd.myapp.type1+json
and "/recipes/xxx/activities/2" would have
Content-Type: application/vnd.myapp.type2+json
But, apart from introducing new technical considerations (do we really want to fetch this data in multiple steps?) still the "activities" endpoint would return view models of arbitrary types
Is this the right approach to tacke this design issue? is there any "restful" way that ensures client and server can agree on a contract without any "dynamic" interpretation needed nor parsing magic?