http://amundsen.com/media-types/collection/examples/
This format takes into consideration collections (much like Siren). It also takes into consideration versioning. However, I'm not certain version matters in the data set if it pertains to an API version. That is best left being in the API URL. It could pertain to collection version, but I'm not sure the point. Documentation says each collection should have a version - but says nothing more about meaning or why.
Items are clearly distinct in this format and are organizationally positioned separate from links.
This is by far the most collision free structure.
However, the data format itself is a bit strange...Every field being an array. Data is always an array of objects. I understand the flexibility this presents and am not 100% against it. I just believe it's perhaps not needed as things could change based on the client application.
The queries section is very nice and something not found in other formats. However, I don't see anything for pagination and I believe it would certainly make sense to include by now.
Collection+JSON puts a lot of emphasis on the display and intended usage of data. Moreso than any other format. This is nice, but unless the client application was attempting to display a layout automatically, I don't see the need. A human engineer can interpret and decide things just fine and perhaps different clients or even access control rules would dictate a different visual representation anyway. Therefore I believe this oversteps the duties a little bit. Still clever and guidance/definition is what we're after of course.
I like how links are even more separate from the data here than any other format. Due to this structure, there is no need to prefix with underscores, etc. Links still carry the same "rel" descriptive values which are important for orientation.
However, I would still use "self" instead of "href" for the current item's link for consistency. Again, Collection+JSON puts some emphasis on how these links should appear. For example, the "render" key. However, many of these properties "render" and "prompt" etc. are optional anyway.
The only downside here is that given how much emphasis and careful consideration is put on how data is rendered, there seems to be a lack of emphasis for "actions" or forms.
The "template" section is actually intended to be used as a guide for which data should be sent to the API in these cases (POST and PUT for update, following convention). However, I don't believe it's particularly descriptive. Also, the format states there should only be one form. This isn't a bad rule of thumb, but I could see where an API response may return multiple forms every now and then (related data, etc.).
http://amundsen.com/media-types/collection/examples/#ex-error
Not shown here is another section called "errors" and I feel this is important and worth mentioning. It's very debatable that errors should be contained within HTTP reponse headers...But I believe that, often, additional detail is required and messages being returned in an API are good because it means those messages can be updated from one central location instead of many client application updates. Superior design for maintenance. Additionally, HTTP headers should be kept small and while a status code is obviously present, an entire message intended for a human is perhaps inappropriate.
{ "collection" :
{
"version" : "1.0",
"href" : "http://example.org/friends/",
"links" : [
{"rel" : "feed", "href" : "http://example.org/friends/rss"}
],
"items" : [
{
"href" : "http://example.org/friends/jdoe",
"data" : [
{"name" : "full-name", "value" : "J. Doe", "prompt" : "Full Name"},
{"name" : "email", "value" : "[email protected]", "prompt" : "Email"}
],
"links" : [
{"rel" : "blog", "href" : "http://examples.org/blogs/jdoe", "prompt" : "Blog"},
{"rel" : "avatar", "href" : "http://examples.org/images/jdoe", "prompt" : "Avatar", "render" : "image"}
]
},
{
"href" : "http://example.org/friends/msmith",
"data" : [
{"name" : "full-name", "value" : "M. Smith", "prompt" : "Full Name"},
{"name" : "email", "value" : "[email protected]", "prompt" : "Email"}
],
"links" : [
{"rel" : "blog", "href" : "http://examples.org/blogs/msmith", "prompt" : "Blog"},
{"rel" : "avatar", "href" : "http://examples.org/images/msmith", "prompt" : "Avatar", "render" : "image"}
]
},
{
"href" : "http://example.org/friends/rwilliams",
"data" : [
{"name" : "full-name", "value" : "R. Williams", "prompt" : "Full Name"},
{"name" : "email", "value" : "[email protected]", "prompt" : "Email"}
],
"links" : [
{"rel" : "blog", "href" : "http://examples.org/blogs/rwilliams", "prompt" : "Blog"},
{"rel" : "avatar", "href" : "http://examples.org/images/rwilliams", "prompt" : "Avatar", "render" : "image"}
]
}
],
"queries" : [
{"rel" : "search", "href" : "http://example.org/friends/search", "prompt" : "Search",
"data" : [
{"name" : "search", "value" : ""}
]
}
],
"template" : {
"data" : [
{"name" : "full-name", "value" : "", "prompt" : "Full Name"},
{"name" : "email", "value" : "", "prompt" : "Email"},
{"name" : "blog", "value" : "", "prompt" : "Blog"},
{"name" : "avatar", "value" : "", "prompt" : "Avatar"}
]
}
}
}
First, if there's any JSON formatting errors it was an oversight (these are thoughts not actual code). The intention is typical JSON of course.
I was thinking about #2 in some of the alterations I'm making now and decided to only support one level of "embedded resources" for now. With the above format I was not even using embedded resources (to answer #3). My goal was basic CRUD. Again, I'm designing for a different/broader case now. My thinking on keeping one level of embedded resources is that anything deeper and more complex would require another HTTP request. A single level allows for navigation. My fear with having a very deep response is performance and confusion. Everywhere performance. Parsing. Generating. Response payload size. This may change in the future though.
#4 I'm ditching _http ... I'm ditching _actions (consolidating to _links) but keeping _meta because many APIs do return things like "response time" etc. I believe there is a universal use case here, but it's completely optional of course. I want good support and good flexibility. So having "_meta" as a misc. bucket for things outside the concern of resources and links made sense to me.
#5 Yup, I need to look into the best way to do that (I was jotting down ideas borrowed from some routers in various frameworks). Thanks for the link. That's super awesome.
#6 Makes sense. I was not using CURIEs before, but am going to now. As for IANA that's fine it's supported here. People can plug those in as desired. I don't care that "skip" isn't in IANA. It doesn't make the format any less valid. It may make more sense to use in a CURIE and that's cool.
Moreover, "curies" isn't on that IANA list either. So again... _curies and not curies fits better in my opinion.
Thanks for the notes. Super helpful and much appreciated.
I do still wonder why curies can't be _curies ... Given it's more for HAL compatibility I may stick without the underscore, but I do feel it creates a minor inconsistency with the format I'd like to use.