Skip to content
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

Closed
emmanuel opened this issue Aug 28, 2013 · 72 comments
Closed

Comments

@emmanuel
Copy link

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?

@kevinswiber
Copy link
Owner

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.

@mamund
Copy link

mamund commented Aug 29, 2013

adding my voice here:

i designed Cj to take advantage of the CRUD model PLUS the ability to
describe the details of queries (including possible values) and a "write"
operation (for POST and PUT items in the collection). that means Cj is
basically ATOM + Queries and Templates.

if your model does not lend itself to collections well, Cj is going to be
an uncomfortable fit. i've implemented quite a number of problem domains w/
it, but i eventually run into the limits of item-based CRUD+Query after a
while.

just sayin' ;)

On Thu, Aug 29, 2013 at 3:45 PM, Kevin Swiber notifications@github.comwrote:

Hey @emmanuel https://github.com/emmanuel! This is a frequently asked
question. Pinging @mamund https://github.com/mamund and @mikekellyhttps://github.com/mikekellyto see if they know of any trusted, non-biased, existing comparison.

The biggest differentiator of Siren is Actionshttps://github.com/kevinswiber/siren#actions-1.
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.


Reply to this email directly or view it on GitHubhttps://github.com//issues/15#issuecomment-23517991
.

@mikekelly
Copy link

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

@mikekelly
Copy link

.. 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

@zdne
Copy link

zdne commented Aug 30, 2013

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.

@ericelliott
Copy link
Contributor

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.

@emmanuel
Copy link
Author

emmanuel commented Sep 4, 2013

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.

@cainus
Copy link

cainus commented Sep 15, 2013

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.

@ericelliott
Copy link
Contributor

image

@mikekelly
Copy link

☝️

@cainus
Copy link

cainus commented Sep 15, 2013

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.:

  • what to name the object
  • if the object should be an array or hash
  • how to denote rels
  • how to denote hrefs

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.

@mamund
Copy link

mamund commented Sep 15, 2013

Gregg:

we have a number of designs created here. usage of those designs matters.
the design most often used are the design most worthy of adding to the list
of RFCs.

every app you build is a vote. every client that requests a server support
media type X is a vote. every server that add support for media type X is a
vote.

if it turns out none of the current designs are getting enough votes then
someone needs to create some new designs. ones closer to that which devs
want to use.

its simple, but not clean. its effective, but not efficient. and its what
we have ;)

On Sun, Sep 15, 2013 at 6:00 PM, Gregg Caines notifications@github.comwrote:

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.:

  • what to name the object
  • if the object should be an array or hash
  • how to denote rels
  • how to denote hrefs

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.


Reply to this email directly or view it on GitHubhttps://github.com//issues/15#issuecomment-24481272
.

@cainus
Copy link

cainus commented Sep 15, 2013

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.

@mamund
Copy link

mamund commented Sep 16, 2013

gregg:

yep - all the things you mention are an issue. if it turns out there are
some minor details you don't like but can live with, then that's proly the
media type to start with.

keep in mind that HTTP lets both servers and clients select matching media
types at runtime (content negotiation). when you build your app (client or
server) you can make representation of the internal object graph a "layer"
or black box in your implementation model:

string representation = createOutput("application/hal+json", userObject);

now, future media type choices only need you to update the createOuput and
pass the new argument.

this "future-proofs" your work and lowers the risk of embedding a single
representation format into all your apps.

On Sun, Sep 15, 2013 at 7:19 PM, Gregg Caines notifications@github.comwrote:

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.


Reply to this email directly or view it on GitHubhttps://github.com//issues/15#issuecomment-24482825
.

@ericelliott
Copy link
Contributor

@cainus _links vs links matters because the formats that are using _links largely MUST do something like underscore to prevent collisions with the keys for objects being represented. That's the major problem I see with formats that mix the represented object keys with special keys. If it weren't for that, you could easily change the name of the links collection, and it probably wouldn't matter much.

@mikekelly
Copy link

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]) 😆

@ericelliott
Copy link
Contributor

@mikekelly Actually, I think HAL's use of rel as an object key is weird.

  1. Because you might want to use the same rel for multiple links, and
  2. Because you might want to represent a single link with multiple rels

Either way, you have to do awkward things to make that happen. More awkward, I think, than selecting a link from an array.

@mikekelly
Copy link

Yes, we have different opinions - and that's ok..! But I'll bite anyway:

  1. this has always been possible with hal+json since properties in the _links object can be either an object or an array, i.e.
{
  "_links": {
     "many-things": [{ ... link ... }, { ... link ... }],
     "one-thing": { ... link .... }
  }
}
  1. I already made this point, but it's not really a very strong one because:

a) it's fairly easy to argue most people don't need or want to do this most of the time (it's "advanced")
b) anyone wanting to do this can express a multi-rel link in HAL as multiple links with the same target URL - and this can be worked backwards into the same info a multi-rel link would convey fairly easily.

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.

@mikekelly
Copy link

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];

@kevinswiber
Copy link
Owner

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.

[1] http://tools.ietf.org/html/rfc5988

@ericelliott
Copy link
Contributor

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?

@mikekelly
Copy link

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:

3.  Links

   In this specification, a link is a typed connection between two
   resources that are identified by Internationalised Resource
   Identifiers (IRIs) [RFC3987], and is comprised of:

   o  A context IRI,

   o  a link relation type (Section 4),

   o  a target IRI

@mikekelly
Copy link

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:

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];

@mikekelly
Copy link

to be fair Siren is a bit less complicated:

response.links.filter(function(link) {
 return link.rels.indexOf('thing') != -1;
})[0];

.....

:trollface:

@kevinswiber
Copy link
Owner

@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.

@kevinswiber
Copy link
Owner

@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.

@ericelliott
Copy link
Contributor

@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');

@glennblock
Copy link

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!

@gpittau
Copy link

gpittau commented Nov 28, 2013

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

@paulwalker
Copy link

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.

@paulwalker
Copy link

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.

@zdne
Copy link

zdne commented May 23, 2014

generic client state transition workflows

That. Generic client = state machine interface.

(sorry for hijacking the topic :)

@kevinswiber
Copy link
Owner

@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?

@kevinswiber
Copy link
Owner

generic client state transition workflows
That. Generic client = state machine interface.

(sorry for hijacking the topic :)

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. ;)

@paulwalker
Copy link

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:

  • URI Templating (Siren provides the oft used rel next/previous examples, but how to describe a URI to arbitrary page in a list?)
  • URI-Reference, relative URIs, URI resolution
  • targetSchema (i find the possibility that other media types may be described as possible responses intriguing. input: crop dimensions, output: re-cropped image)

@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 :-).

@apsoto
Copy link

apsoto commented May 27, 2014

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.

@paulwalker
Copy link

@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?

@geraintluff
Copy link

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 "datetime" or "reset" that map very intuitively onto HTML form controls). JSON Schema is more focused on the data model - you can say a lot of the same stuff (e.g. {"format": "date-time"}) as well as arbitrarily complex input structures, but controls like "reset" that don't produce any data aren't covered.)

@paulwalker
Copy link

Well, the field type definitions are lifted directly from html5 input types so it's a direct mapping. I suspect the inclusion of the reset type was not intentional as submit was purposely removed.

@apsoto
Copy link

apsoto commented May 27, 2014

@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.

    JSON.parse(response.body).should match_json_schema "user"
    JSON.parse(response.body).should match_json_schema JSON.parse(schema_string)
    JSON.parse(response.body).should match_json_schema File.read("someschema.json")

RSpec::Matchers.define :match_json_schema do |expected_schema|
    match do |actual_json|
      require 'json-schema'
      expected_schema_hash = JSONValidate.local_schema_for(expected_schema)
      @errors = JSON::Validator.fully_validate(expected_schema_hash, actual_json)
      @errors.nil? || @errors.length == 0
    end
end

@kevinswiber
Copy link
Owner

@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 :-).

@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. :)

@kevinswiber
Copy link
Owner

@geraintluff

Thanks for joining the party. :)

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.

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.

(A secondary observation is that Siren seems to focus more on presentation (e.g. there are input types like "datetime" or "reset" that map very intuitively onto HTML form controls). JSON Schema is more focused on the data model - you can say a lot of the same stuff (e.g. {"format": "date-time"}) as well as arbitrarily complex input structures, but controls like "reset" that don't produce any data aren't covered.)

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.

@kevinswiber
Copy link
Owner

@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.

@apsoto I think this is a great way to use JSON Schema with Siren. Thanks for sharing.

#megathread

@ericelliott
Copy link
Contributor

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.

@ericelliott
Copy link
Contributor

Another note - many of JSON-Schema's validation rules can be automatically converted to Siren's HTML5-based form field validations.

@paulwalker
Copy link

the features you listed do not exist in Siren
However, I do not see how JSON Hyper-Schema and Siren are even competing

Yep, not seeking a vs battle, can we grow Siren though? Let's start with relative URIs at least?

@faassen
Copy link

faassen commented Sep 29, 2014

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.

@kevinswiber
Copy link
Owner

@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.

@faassen
Copy link

faassen commented Oct 2, 2014

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.

@lanthaler
Copy link

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

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests