Hmm… the only compliant solution I can think of right now that lets you signal relationships, include the legacy data, and not confuse generic clients would look like this:
{
"data": [{
"type": "newentity",
"id": "...",
"attributes": { /* ... */ },
"relationships": {
"legacyentity": {
"meta": { "legacy-data": {"type": "oldstuff", "id": "1"} }
}
}
}],
"meta": {
"legacy-included": [ /* ... */ ]
},
"included": { /* ... */ }
}
Above, "legacy-data"
works just like standard "data"
, except that it points to legacy objects that show up in "legacy-included"
rather than standard "included"
.
The key thing making this compliant is that the "legacyentity"
relationship object has a "meta"
key, because a relationship object is allowed (strangely) to just have "meta"
.
The primary advantage this has over the solution you mentioned earlier is that it doesn’t put any legacy entities in "included"
—doing that is sure to trip up generic clients which expect "included"
to contain proper resource objects.
The downside, I guess, is that all that "meta"
looks a little ugly.
Once the profile extension mechanism is finalized, it’ll be possible to solve this more elegantly, as there’ll be a spec-compliant way for you to include new keys in the document (and even define their meaning in a way that other clients can reuse). That is, you’d be able to do something like this:
{
"data": [{
"type": "newentity",
"id": "...",
"attributes": { /* ... */ },
"relationships": {
"legacyentity": {
"legacy-data": {"type": "oldstuff", "id": "1"},
// meta would technically still be needed here
// for compliance, but it can be empty
"meta": { }
}
}
}],
"legacy-included": [ /* ... */ ],
"included": { /* ... */ }
}
If you control all the clients for this API, and you’re willing to do some find and replace modifications later, you could even implement the profile extension version now and then just tweak your implementation once the details of the profile extension mechanism codify.