-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
What's different/better/worse than other JSON hypermedia media types? #15
Comments
Hey @emmanuel! This is a frequently asked question. Pinging @mamund and @mikekelly to see if they know of any trusted, non-biased, existing comparison. The biggest differentiator of Siren is Actions. I believe the closest Collection+JSON gets with this is write templates. HAL has no concept of inline input metadata for submitting requests, though there was something called HALO that I think may have supported that at one time. (I'm sure the authors will correct me if I'm wrong. :) Siren also has a concept of "class." The class attribute may contain multiple descriptors of the current representation. I've avoided calling these "type descriptors." They act more like "mixin descriptors" (i.e., if an entity is of a certain class, it may have properties, actions, sub-entities, or links associated with it). When layering a UI on top of Siren, I've also used the class attribute to act as a view router (e.g., When a representation comes back with an "error" class, route to the error view or when a representation contains a "home" class, route to the home view... or some combination... When a representation has both the "home" and "error" classes, display the error alongside the home view.) This could also be done in an M2M scenario. For HAL, that "class" type information would be contained in the link relation documentation. I think for Cj, that info would have to be an attribute inside the data array or in the link relation documentation. Again, I'll let the authors chime in if this is incorrect. |
adding my voice here: i designed Cj to take advantage of the CRUD model PLUS the ability to if your model does not lend itself to collections well, Cj is going to be just sayin' ;) On Thu, Aug 29, 2013 at 3:45 PM, Kevin Swiber [email protected]:
|
HAL is geared towards "m2m" APIs. Its deliberately minimalistic in its design, so as Kevin rightly points out it has no concept of inline forms. It is very focused |
.. on the use of link relations to describe the possible transitions of an application. It is not difficult to process, in fact you could consume HAL the same way you would any normal JSON and you won't be caught out by any magical rules! HTH!! Thanks for copying me in @kevinswiber |
This is very helpful discussion! I was asking Kevin the very same question couple months ago. However it is invaluable to get the point of view of the authors of other formats! Personally I was not aware of the Percolator format until today. I have asked @cainus, author of Percolator.js, about the motivation behind the Hyper+JSON. You can find his very informative answer here. Apparently everyone was tackling the problem with a different use-case on mind, but to me Kevin and Gregg had somewhat similar goal in the support of an arbitrary "form / action" for a link while HAL stays as sparse as possible. |
The one thing that I dislike about HAL is that is is so minimal -- that is intentional, of course, but it mixes the hypermedia metadata in with your actual application data, leaving the client to sort it out. I'm sure that works for a lot of use-cases, but it rubs me wrong. I'm a fan of both Collection+JSON and Siren, where there is clear, consistent separation between the hypermedia elements and your application data, as well as a slightly richer vocabulary for expressing hypermedia concerns. However, if you don't want to build or use a client / library that knows how to interpret that vocabulary and extract your application data, that is where HAL really shines -- it should just work out of the box. You could easily add it to an existing project without changing much of anything, which would make it very easy to gradually transition an existing system to a more hypermedia-aware API. |
This is extremely helpful. Frankly, I'm delighted and humbled to have insight "from the horse's mouth(s)" (er, content-type authors) about the motivations and differences between these formats. I've been working in a big company for a little bit, I didn't do nearly as much open source related work in the last year as I had in each of the previous 5, and I almost forgot how phenomenal the open source community is. Thanks everyone! ...closing because I think this question is now satisfactorily answered. Future askers can be directed here for enlightenment. |
I'm not sure if anyone else is thinking this too, but wouldn't it be a huge boon to hypermedia APIs if we all got together, determined the lowest-common-denominator for links in json, and came up with a proposal? There are so many formats now, and they do have a lot of similarities and commonalities. I know we disagree on a number of points, but I bet there is enough that we agree on that we could present a unified proposal, one that is still compatible with the formats that we're individually proposing. |
☝️ |
Too true :) But who actually thinks we have competing standards? Writing up some RFCs or even getting IANA approval doesn't mean standardization has been accomplished. There needs to be widespread usage. And none of these frameworks and media-types have achieved that. That makes now a great time to standardize. We've seen how our different media-types actually work in the real world, and what matters and what doesn't, but there's no actual widespread usage (yet). BTW... I'm just talking about standardizing on a problem that we've all had to solve: links in json, eg.:
We're actually all very close and I don't see any valuable reason whatsoever for the minor dissimilarities. Does anyone else? Are there really competing design goals on those issues? I could certainly sacrifice some of my minor design goals for the bigger goal of inter-operability. |
Gregg: we have a number of designs created here. usage of those designs matters. every app you build is a vote. every client that requests a server support if it turns out none of the current designs are getting enough votes then its simple, but not clean. its effective, but not efficient. and its what On Sun, Sep 15, 2013 at 6:00 PM, Gregg Caines [email protected]:
|
Well I'd definitely agree if not for the fact that I'm only talking about the differences that at this point don't appear to matter. If I'm being dense and you've seen a huge impact in actual usage by calling the object "_links" vs "links", please let me know. On the contrary, these types of APIs have been out for years now, and I haven't heard anyone choose one format over another based on that (It seems we're even unanimous on using the word "href" as the property name for the url. That could be a start!). The worst part (to me at least) is that we're all independently working on many of the exact same problems. These differences are hampering tooling and interop, and the proliferation of hypermedia apis in general. Anyway... I'll drop it. I honestly hope any (or all) of these formats gains a huge following someday because that'll mean widespread use of hypermedia apis. |
gregg: yep - all the things you mention are an issue. if it turns out there are keep in mind that HTTP lets both servers and clients select matching media string representation = createOutput("application/hal+json", userObject); now, future media type choices only need you to update the createOuput and this "future-proofs" your work and lowers the risk of embedding a single On Sun, Sep 15, 2013 at 7:19 PM, Gregg Caines [email protected]:
|
@cainus |
Yes, collisions might happen but the media type could just make "links" with no underscore a reserved property and force implementors to work around it. That would be a valid decision and in practice it would probably only affect a small % of people. There are bigger distinctions though, e.g. most other media types model links as an array, whereas HAL uses an object and the rels as keys. Link relations are the primary means of identifying a link, so I think HAL's approach makes the best use of JSON to present that - some people worry more about the edge case in which someone may want to represent one link with multiple rels (and don't want to have to represent these as multiple links to the same URI) so they instead model it as an array and establish rules for plucking out the links. fwiw, judging by personal experience, the latter is never actually necessary (is not worth the convolution) and is basically a poor design decision - that's just my opinion but unless someone comes up with hard evidence to the contrary I can't see my opinion on that changing and (although it might seem trivial) I actually think it matters so I wouldn't want to change that about HAL. But I also think that's ok, there's a whole bunch of libraries available for serving and consuming HAL - and I think there's a bunch for cj and siren too. All the projects seem to get along fine alongside each other, some libraries cover many of them (roar that @mamund mentioned does this). In the end, if you are concerned about fragmentation - you should pick a horse and evangelise it. I suspect that adoption over the next couple of years will be driven by who makes the most noise (i.e. writing books, blog posts, tweets) telling people how they should be using/doing things.. and, fwiw, that might be a reason not to pick he hal-horse because I barely even have enough spare time to edit the damn thing these days! 😞 I'm tempted to hand it off to someone else, actually. I just need to find someone I can trust not to try and stick anything form-like in it. (joking [kind of]) 😆 |
@mikekelly Actually, I think HAL's use of rel as an object key is weird.
Either way, you have to do awkward things to make that happen. More awkward, I think, than selecting a link from an array. |
Yes, we have different opinions - and that's ok..! But I'll bite anyway:
{
"_links": {
"many-things": [{ ... link ... }, { ... link ... }],
"one-thing": { ... link .... }
}
}
a) it's fairly easy to argue most people don't need or want to do this most of the time (it's "advanced") It makes more sense to me to have the easier affordance for the simpler, common use-case; and the more difficult affordance for the more complicated, uncommon use-case. |
Addressing a single link: HAL-way: response._links.thing; Array-of-multi-rel-links-way: response.links.filter(function(link) {
return link.rel.split(' ').indexOf('thing') != -1;
})[0]; |
I'm going to call bike-shedding on the links issue. I think we've defined capabilities for both models. Siren supports in-message link representations that correspond with the fields used by Web Linking RFC5988[1]. This also aligns with HTML, which isn't too uncommon for Siren. An earlier design even used space-separated strings to depict arrays. I found this silly and just added a couple of square brackets. To my taste, looking at a couple of brackets is a fair compromise to avoid checking the type of the value at parse time and executing conditional logic. ("Is it an array or a string... or an object... or a...?"). Having a known, reliable object structure for Siren messages has been a benefit to me during implementation time. HAL is intended to be minimal, and so compromises are made to support that design constraint. IMO, HAL has acted as a good on-ramp for developers wanting to take their existing API and support Web Linking without breaking older clients. It continues to do so successfully. Siren is intentionally full of features. Some of these features may be more than what some developers need. That's okay. Much of a Siren entity is optional. I'm disinclined to change the design of Links to something that creates incompatibilities with RFC 5988. From my point of view, there's a huge benefit to capitalizing on an existing specification (i.e., Siren itself doesn't have to do much re-specifying). I've been in a few conversations around convergence of specifications. I don't think we're there yet. In my mind, while there is a lot of overlap between available JSON hypermedia types, they are crafted to be optimized for different use cases. This creates a richness in diversity, and that's something to be celebrated. |
I agree. HAL is good for its use-case, but I don't see the HAL model as a general solution for everything. Likewise, converting an existing API to Siren or Collection+JSON might be a slightly more difficult task than converting it to HAL. I don't see a strong case for convergence between HAL and Siren or Collection+JSON, but maybe there are enough similarities in Collection+JSON and Siren linking to use the same link standard? |
for the record, it doesn't create incompatibilities with the web linking spec: it just makes achieving one small part of the spec (namely the multi-rel capability of the Link header serialisation) more cumbersome. It's also worth noting that the wording of RFC5988 actually implies that "a link" is a singular relation between two IRIs:
|
Worrying about underscore prefixes is bike-shedding. This issue of using an array or an object, isn't. It's fairly fundamental to a hypermedia type - hence:
|
to be fair Siren is a bit less complicated: response.links.filter(function(link) {
return link.rels.indexOf('thing') != -1;
})[0]; ..... |
@cainus @dilvie I'm still unclear as to what the benefit is of converging on a subset of a media type. When writing handlers for multiple media types, it seems to me that link parsing isn't as big of a deal as handling the different semantics available between types. If link semantics match, but everything else is fundamentally different, what is the gain, exactly? I feel like I'm missing something. Help me out. @mikekelly Ah, I must be taking the multiple-rel hint from HTML then. Thanks for the correction. |
@mikekelly Re: finding links Most developers won't even know this implementation detail and will just use a library that handles it automagically. I don't see it as being a big deal. Parsing any of these formats is relatively easy. Once specs are stable, this is often a "set it and forget it" situation. It's more important to focus on enablement. What does this media type enable? I've been speaking with folks interested in Siren because it supports dynamic workflows. I don't know any other JSON-based hypermedia type better at that use case. |
@mikekelly It's pretty trivial to abstract the link retrieval differences away in clients. The first thing I did when I started using Collection+JSON and Siren is write a model for hypermedia responses that lets you do: var richResponse = hyper(response);
richResponse.links.get('someRel'); |
Good thread. My personal opinion is all these efforts are goodness. Each of the media types have their own benefits and ideal uses cases though there is overlap with some. HAL for example can be used with almost anything, but Siren and CJ bake in deeper support for specific scenarios. Use whatever works, the web arch can easily accommodate all of them! :-) Share your experiences when you do so we can all benefit. I think this kind of discussion is constructive so we can see the goals of each, but if I could have my druthers I would never wish for one media type to rule them all. Thank you @mikekelly, @mamund and @kevinswiber for pushing on the space and helping us to advance our understanding! |
what really matters is what makes them incompatible with each other... I mean: if I can implement a layer for HAL resource consumption, and, I can then replace that by one which consumes siren, from my client perspective both media-types are compatibles. Now, if HAL does not provide forms or X does not provide embedded links, my client can not be abstracted from the representation and will need to be too smart. ...thinking in terms of HFactors |
I picked up @mamund's book (the physical edition even!) about a year ago and finally cracked it open as I've recently just started a new project. And now I've stumbled upon what appears to be the canonical discussion comparing the various hyper media types of out there from the authors themselves. While the actual topic may have been whether an attempt should be made to unify, it's certainly served as an informative comparison to me at least :-). The funny thing is, last time I started a JSON API from scratch five years ago...I sprinkled my JSON with meta-data so very similar to what @kevinswiber has defined here with Siren...I used an actions object with key/value objects to describe the various API resources right down to fields including validation data like min and max fields. Looking for a standard for this sort of thing a few years back, the closest I could see was what Google started doing with their discovery apis based upon JSON schema: http://tools.ietf.org/html/draft-zyp-json-schema-04. My question for you guys (including you @mikekelly) is whether or not you considered JSON schema to solve some of the same problems that you are now using your respective media types for? For the last few years, I have considered the use of JSON schema in some fashion as the preferred approach to building discoverable, connected/linked JSON APIs, but now I'm obviously starting to question that. |
Also, FWIW, in my experience the metadata in my JSON paid immediate dividends in human consumption with both web and mobile teams furiously consuming the functionality. Right away the developers saw the value in parsing urls from a hash rather than hard coding them and eventually generic client code sprouted from using the field data for validation to a full on generic library that for non form based functionality with a UI test harness to boot. I never realized generic client state transition workflows or anything from it, but that's certainly interesting if perhaps overly ambitious. |
That. Generic client = state machine interface. (sorry for hijacking the topic :) |
@paulwalker Yes, I've looked at JSON Schema, but I think it's solving for a different (though related) problem space. The obvious fit is in using it to describe the shape of request or response bodies. How do you see it being used to augment existing media types? |
I'm currently working on a project using Siren to model resources as state machines. Representations reflect the current state and available transitions. This is for an open source Internet of Things platform. This happens to be a really great place for hypermedia, because devices-as-state-machines is a great model. I'm looking forward to exploring more in this space. (@zdne, I know you know this already. Just informing others. ;) |
Hi Kevin, Thanks for the response, I hope you are enjoying your Memorial day weekend. Right, the most obvious overlap is in the description of the accepted request bodies as described in Siren's actions. My initial thoughts were that the use of JSON schema was more appropriate than HTML5 input types, but I do see the value of a more rich set for browser based javascript clients (a use case I certainly have an interest in). While it may not map exactly to the capabilities of other clients, it is more descriptive than JSON schema's seven primitive types and I certainly can envision a mobile or desktop clients taking advantage of this. Additionally, since I posted my original question I have now come across JSON Hyper-Schema. Obviously the overlap of problem space is much greater between Siren and JSON Hyper-Schema, so I'd like to include the authors @kriszyp @garycourt @geraintluff in case they have some thoughts. There are other elements of JSON schema/hyper-schema I can see value with:
@kevinswiber, not trying to stir up a hornet's nest...at the end of the day, I simply want to develop a JSON API that robustly (completely?) describes it's own input/output :-). |
A bit off topic, but FWIW I've been using a JSON schema against a Siren API in my CI build just to make sure I don't break backwards compatibility (removing a property, action, etc). I guess my point is that Siren and JSON Schema can be complementary. |
@apsoto Not at all off topic. I'd like to do the same sort of thing for input validation on the API. And I'd love if the stack I used did it for me! I feel we're not far from that, but it all starts with a reasonable http media type/; foo/whatever; format=/getshitdone so we can all get busy creating this sort of stuff. How do you generate/maintain your schema (vs spec tests)? Wouldn't it be nice if you didn't have to define all this in multiple places? |
I agree, JSON (Hyper-)Schema and Siren look similar in many ways. Both specify client-server interactions and describe links between items, et cetera. I'm not completely neutral on this, and I apologise if I've misunderstood some fundamental things about Siren, but here are my impressions: The biggest difference I can see is that Siren is "in-band" - a given piece of data can be described using Siren, and possible interactions for it can be known once the data is received. With JSON Schema, it's more like OO programming - a JSON Schema describes a general category of data. The idea is that you can have very concise data instances, which you combine with the (referenced) schema to infer links/interactions. There are various form-generation tools for JSON Schema, so you can still generate UIs/clients, but its strength is API description. The ahead-of-time nature of this description means that as well as validation (server-side and client-side), you can auto-generate documentation - or even client libraries in various languages. (A secondary observation is that Siren seems to focus more on presentation (e.g. there are input types like |
Well, the field type definitions are lifted directly from html5 input types so it's a direct mapping. I suspect the inclusion of the |
@paulwalker I hand rolled the schemas and then wrote a rails integration spec test with a custom matcher to validate an api response against a json schema. I'm using the json schema ruby gem. Hope this snippet below can point you in the right direction.
|
@paulwalker I happen to be one of the few who believes a place exists for all this technology. In fact, I think it's great. We can't advance if we live in an isolated land of theory without branching out to the broader world of practice. The way to do that is by sharing our thoughts and building software. It's true; the features you listed do not exist in Siren. However, I do not see how JSON Hyper-Schema and Siren are even competing. Can they be complementary? Or is the entire premise of JSON Hyper-Schema that all affordances belong in a metadata document? If it's the latter, I disagree with that for several reasons, but I'll save 'em for now. :) |
Thanks for joining the party. :)
Yes, this is true. The design is intentional. Siren believes the availability of state transitions is a decision made at runtime by the server. The ability to insert any number of hidden fields in a transition is a way to maintain statelessness, as well, even through server evolutions. I'm not making a judgement call of "right" or "wrong," but I do believe the design goals differ.
Siren borrows HTML5 input type definitions. The older input types are unfortunately named, even for HTML. If you read the descriptions of these input types in the HTML specification, such as checkbox, you will see no mention of "square boxes that show a checkmark when selected." The definitions do not focus on the presentation. In practice, I often decompose complex input structures into simpler action fields. This reduction of data shape complexity will not always be an option, but it has worked for me thus far. It actually makes me revisit my design when I encounter a use case like this. That said, Siren documents could be extended to allow "schema" attributes on input fields. We don't have an official model for extensions (or a way to broadcast their existence in a representation) at this point, but it's something we've talked about on the Issues list and on the Google Group. |
@apsoto I think this is a great way to use JSON Schema with Siren. Thanks for sharing. #megathread |
I'm using JSON-Schema to validate Siren payloads on the server side. I do see a little overlap, but my use is mostly complementary. |
Another note - many of JSON-Schema's validation rules can be automatically converted to Siren's HTML5-based form field validations. |
Yep, not seeking a vs battle, can we grow Siren though? Let's start with relative URIs at least? |
Anyone have any opinions on JSON-LD and Hydra specifically? JSON-LD has some overlap with JSON Schema, and obviously Hydra overlaps with a lot of hypermedia efforts. |
@faassen This thread is too long to remember everything, and it's quite a commitment to re-read. :) I think JSON-LD and Hydra are pretty cool, though I still need to spend more time with them. I learned a lot more about Hydra from @lanthaler at the recent API Craft Conference. Using JSON-LD to describe the shape of API data is a great concept if that's what you need. I believe operations in Hydra need to be defined up front to adhere to a certain schema. If this is true, and I'm sure Markus will correct me if I'm wrong, it doesn't meet my personal requirement of having available transitions be dynamic and defined by the server at runtime. In general, I see value in all these different media types. In this volatile time, I think it does make sense to keep researching and keep trying new things. I won't be hindered by a sense of pride in what I've created, because software is not that simple. Sometimes it's A. Sometimes it's B. Sometimes it's 42. |
The thread was very long and interesting for me to read. I've been spending time with JSON-LD. I like especially the tools for expansion and compaction based on context it offers. I've started tinkering with other tools you could build on top of that. I've also been spending time with Hydra. I have more trouble wrapping my head around Hydra, in part because the spec isn't finished and assumes a bit more semantic web knowledge than I have. If by "operations defined up front" you mean operations like POST, PUT and the like, Hydra allows that to be dynamic. Operations can either come from the resource's representation, so if I understand your use case right you can change what particular schema they accept. For operations attached to the external "API documentation" part of Hydra it is different. Hydra allows the API documentation to change dynamically during runtime. This is currently rather casually mentioned in the draft spec (only show particular operations in the API doc if the user has permissions), which set me off on a long discussion with @lanthaler about how this doesn't fit my notion of "API documentation", and how the client is even to know the API documentation has changed. So I think it's part of the intent of Hydra to allow this kind of dynamism, even though it's too dynamic for me. Now Hydra can solve this in another way by changing the types of the resources. You could for instance have a "post_foos" type that allows a POST operation of schema foo, and a "post_bars" that allows a POST operation of schema bar. Since this doesn't require a reloading of the API documentation at unpredictable times I'd rather it talked about that approach more in the spec. You got me wondering now what happens if Hydra sees a resource with both types. Does it accept both schemas? I think so, but the spec needs to become more explicit about that too. |
Yep, this is wrong :-) Hydra allows you to either define operations upfront in what we call an ApiDocumentation or embed them directly in the responses returned by the server. Have a look at these slides, they illustrate both: http://www.slideshare.net/lanthaler/creating-awesome-web-apis-is-a-breeze/37 (Slide 43 obviously just shows a snippet of the complete ApiDocumentation) |
Some sort of comparison with other well-known JSON media types would really help me evaluate which of these I should use for a given service.
HAL+JSON (Hypertext Application Language) is the oldest of these of which I'm aware (originally published in mid-2011). Its author Mike Kelly has also produced a corresponding XML media type.
Collection+JSON is detailed in the book Building Hypermedia APIs with HTML5 and Node, by Mike Amundsen. I don't think there is a corresponding XML media type.
Finally, Percolator.js for Node.js has a sort-of/kind-of media type in its default production of JSON responses.
What's better/worse/different about Siren than any of the above?
The text was updated successfully, but these errors were encountered: