And that is why any sane (experienced?) API and/or standard author should have versioning in mind at all times. In my experience there is no such thing as "the" API or "the" standard.
Their API is versioned (the json api version happened to be v2). But they don't feel the need to build a brand new v3 just to chase a moving target, especially since customers (and they themselves) are already using their v2.
There was an unversioned spec posted for months that looked usable, then suddenly they announced a complete rewrite as "RC2". Calling it a relase candidate was misleading, though - almost everything got changed again for "RC3".
I definitely can see why you'd see RC3 as a complete rewrite, but I don't understand why you'd feel that way about RC3. There were definitely changes, but they were much smaller and motivated by significant feedback by users who opened issues in response to RC2.
For example, RC2 mandated that all fields were dasherized. We made field names opaque in RC3.
At this point, we're pretty much nailing down tiny details and included this language with RC3:
JSON API is at a third release candidate state. This means
that it is not yet stable, however, libraries intended to
work with 1.0 should implement this version of the
specification. We may make very small tweaks, but
everything is basically in place.
From the example on the first page, it just looks like what is needed is a JavaScript object graph tool like JSOG [1], which will allow a large cyclic object graph to be serialized and deserialized to / from json.
In case you're thinking, "Wow, I bet in the real world this would be a misery to impose on a team - I'm sure no one would really want to do this!", well, I worked briefly with a team where they imposed this. It was part of the reason why I say "briefly".
Well, obviously it's very prescriptive. In theory that should mean it requires less mental effort because it tells you what you should be doing - in practice, I found it required more effort to do things the precise way it wanted. I was far from alone in this belief.
My main issue was with the "related/linkage" stuff (which may or may not have changed somewhat since I was exposed to it), which is unpleasant, to my eyes, in the way it is expressed, and also verbose and often duplicative in what it produces.
A related problem was the Node.js implementation we were using, which generally felt like more of a hindrance than a help (and which we ended up extending beyond all recognition, making matters dramatically worse - though that was no fault of JSON API itself directly, other than by association).
At Gragg, I've been experimenting with a different approach: I wrote a self-describing schema language for all of the JSON payloads that'd be sent, wrote a service and tested it with a "blob" type that doesn't validate, then wrote the spec when it was clear enough, then it turns out that writing a client from the spec is usually super-simple, you get to see all of the things which the spec can do.
Here's the basic things that have been mostly useful:
Maybe x, for optional parameters.
Process by defining what to do when null.
Doesn't have to be tagged to be useful.
Repetition in the form of [x] and Map String x.
Process only via a for-each loop.
Tagged-sums-of-products: ["tag", arg1, arg2, ...]
Process only with a switch statement dispatching over arr[0].
Record types like {"id": 3, "name": "Gandalf", "color": "grey"}
Feel free to base logic on record.name etc.
Primitives: dates, ints, strings, blobs.
The tagged-sums bit is probably a dealbreaker for me at this time: I picked this up from Haskell and I would not easily let go. The syntax in JSON is a little clumsy, but it's still important. Cf. Abelson and Sussman's lectures, "All interesting programs start with a case dispatch."
You might want to add http://loopback.io/ which is a node.js module to implement JSON APIs. It has its own way to do it so we could say it's a standard from the industry. Maybe it's too early to call is "standard" but it's getting traction. They're sending people around to give talks and 1 hour training events. I'm coordinating a team of developers using it. So far it's OK.
I was recently exposed to this standard on a green field sinatra project. It quickly became burdensome to maintain all of the linkages. It really deteriorates your ability to keep things DRY on the JSON generation (we were using RABL). Of course, these problems were exacerbated by the fact that there were other issues with how the data was structured and how the client wanted to access resources.
Any idea if this overlaps even more with RAML? I've seen some projects based around RAML but none so far with JSONApi and I'm trying to understand what advantage there is either way when I don't see JSON being more expressive in this goal.
Besides minor things like _links -> links, it specifies a lot of behavior more explicitly than HAL. HAL is a very minimal specification and intentionally doesn't nail down every corner case, preferring implementors to choose what's right for them, perhaps at the cost of a more powerful generic client
One of my primary motivations when I started this (a few years ago now) was a straight forward representation of graphs of data (including bits of data without dedicated URLs), rather than trees of data.
Consider the case of a blog. Each blog post has many comments. Each post has an author, and each comment has an author. Some of those entities may have dedicated URLs, and others may not. Additionally, the authors are highly repetitive; you want to refer to them by identifier, not by embedding them.
Because a tree of data can be represented easily as a graph, but not vice versa, JSON API provides a straight-forward way to provide a list of records that are linked to each other. The goal is simple, straight-forward processing regardless of the shape of the graph.
At first I was confused by this comment because anything built with links is a graph. Now that I've caught your meaning, and seen the complicated "included" structure, I wonder if it wouldn't have been better to just add an "_id" property to HAL. HAL's designers, however, would probably just say that "author" should be its own resource, and be linked or embedded as required. That is, if it's too heavy to embed, then link it.
On graphs, I was really hoping to see provisions in the spec to support the property graph model, specifically for properties on relationships. We are building APIs that access data in a graph DB, and all the data in the graph has had an obvious representation in the JSON API model except for attributes on edges.
As an example, let's say that my graph DB has People nodes and a MARRIED_TO relationship between two people to indicate they are married. A MARRIED_TO edge could have a "married_on" property containing the date of the marriage.
Where would the "married_on" attribute be represented in JSON API? I could stuff it in the "meta" member of the link object, but that feels loose and hacky. Maybe it could live in the "linkage object" along with the "type" and "id" members. But the linkage object appears to currently be a closed set of only those two members.
Is this requirement to present a full property graph model not as common as I would imagine? I'm a bit behind on my sync with the current state of the spec. This is the first time I've tried to elaborate this need.
One of the primary ways in which JSON API is different from HAL (or JSON-LD) is that it specifies both a format for data as well as a full protocol for fetching and manipulating that data.
Most of the trouble in building a JSON API comes not from deciding on the format, but in nailing down the precise requests and responses that handle common kinds of interactions. This became very clear to me as I worked on Ember Data.
Oh boy, cue the haters. I'd like to address a few things that JSON API gets right, and where it fails horrendously (just in time for 1.0!)
The good:
- It opens a path for standardized tooling among API clients. Rather than having a whole mess of JSON-over-HTTP clients with a hard-coded understanding of the particular API, one could theoretically use a hypertext client to interact with any API using this standard.
- It establishes a baseline of what an API server must implement.
The bad:
- It tries to control not just the media type, but the protocol (HTTP) and server implementation. This is problematic because it dictates how your server must implement its routes, and is tightly coupled with HTTP.
- It tries to be very prescriptive, but it cannot cover all edge cases without being exhaustive. This comes at a heavy burden for implementers to get every part of the specification correct. Despite this, some extremely basic features are missing, such as providing an index document so that a client can enter the API knowing only a single entry point (as it stands now, clients must have a priori knowledge of what resources exist on the server).
The ugly:
- Since so many parts of the base specification are optional MAYs, and there is no prescribed mechanism for feature detection, there is no way to figure out if a server supports a particular feature of this spec without trying to do something and failing.
- The spec has made many breaking changes on the road to 1.0 (as other commenters have mentioned, and there is still room for breaking changes).
At this point, I think that this project gained traction due to the clout of the original authors (Yehuda Katz and Steve Klabnik) and the promise of no-more-bikeshedding, though I would argue that the bikeshedding has just shifted from particular APIs to the spec. Disclosure: I authored and maintained some libraries that implement this spec, and authored another media type for hypertext APIs.
Now that you bring it up, the JSON API specification does not even mention REST or hypermedia actually. What I was trying to get at is that media types don't have to be coupled to the protocol. One can exchange an HTML document over HTTP just as easily as one could transmit that document over another protocol.
> Since so many parts of the base specification are optional MAYs, and there is no prescribed mechanism for feature detection, there is no way to figure out if a server supports a particular feature of this spec without trying to do something and failing
> The spec has made many breaking changes on the road to 1.0
Interestingly, most of the breaking changes on the road to 1.0 were about drastically reducing MAY in favor of MUSTs.
Optional features were moved to named extensions, and there is now an explicit way to negotiate about those extensions.
For anyone who was put off earlier on by the number of MAYs, know that we heard you loud and clear. It may (no pun intended) be worth another look.
For people who have been dealing with the churn of JSON API, represented throughout this thread, I'm genuinely sorry.
Let me try to give some perspective on the history. For a long time, JSON API was more of a set of guidelines than a strict specification. A lot of our early adopters hated all of the MAYs in the spec (you can see examples of that throughout this thread), so we decided to tighten things up considerably towards the end of last year.
That meant trying to eliminate the vast majority of options in the primary spec, and moving all optional features to named extensions that clients could programmatically detect.
Of course, significantly tightening up the semantics forced us to grapple with harder problems and pushed some ambiguities into the light of day. RC2 in particular was an attempt to seriously pare down the scope of the main spec, while making the semantics of what was left stricter. Dan (the primary editor) and I spent countless hours discussing various details, and people contributed hundreds and hundreds of (very useful!) comments during this period about various details.
RC3 was a smaller delta, but I could easily imagine that one of the changes had a large impact on existing APIs.
My overall goal for the project from the beginning was to nail down a full protocol (both the format and the wire protocol) that could be implemented by multiple languages on both sides. Originally, it was created because I was frustrated by the ambiguity of "REST-style API" was during the development of Ember Data.
The earliest versions of JSON API didn't really nail things down well enough to deliver on that promise, but I hope that the latest versions will be able to. Time will tell.
I appreciate the massive amount of work and the recent updates to tighten the spec.
One challenge with the churn is a lack of any high-level changelog (git commit history doesn't count). I have a team working off an earlier version of the spec, and I check back semi-frequently. But I haven't been able to find a document outlining "here are the major changes since the previous versions." I understand that would represent more work on top of work, but for such a large spec, the changes have been disorienting.
We're starting to build API endpoints with this where I work. We didn't have compound documents in an earlier version of our API, and we ended up having to make a lot of roundtrips for some things. So I had been thinking about something like the jsonapi "include" mechanism, and when I saw how jsonapi was doing it, it was pretty close to what I would have done. That made me feel better about going along with their decisions in areas I haven't thought about.
They keep saying that they're closing in on 1.0, but there's a few issues left:
It's good that they want to get all of the breaking changes done so that they can declare a stable 1.0. But it also seems like they're going to try and call it stable right after making a bunch of changes, which seems risky.
I also pitched JSON-LD/Hydra at work, because they're w3c-backed and JSON-LD has some uptake. But the other people who looked at those specs found them hard to digest. And I agree; as an implementer, I can read the jsonapi docs quickly and have a pretty clear idea of what to do. But with JSON-LD/Hydra, not so much.
I get the sense that JSON-LD/Hydra is more flexible than jsonapi, but I think jsonapi does what we need. And if it does what we need, then additional flexibility might actually be a drawback. I guess we'll see how it goes.
Thanks for the feedback. Personally, I feel like we nailed down the important changes earlier this month, and I agree that further churn at this point is likely to cause more harm than good.
For what it's worth, the issues you linked to are mostly about adding more rigor to possibly underspecified areas, not changing things that are already specified, but those things could easily be done after 1.0.
This reminds me of hypermedia API. Generally speaking, you're provided with an index of resources via xml/json, you then fetch those resources which provide a single or many levels of additional results which are fetch-able. In essence, your api data is almost browse-able. Objective is Idempotent response, fetch as little as possible, provide new functionality via new resources, and resources with discover-ability for auto RPC. https://github.com/swagger-api/swagger-spec/
Yeah...no. Standardizing something like this is useless and only full of edge cases. Keep API's free form and flexible without imposing some sort of restriction. That's how you end up with bigger messes than what you started with. API's are not a mess currently anyway. The point of building a unique application isn't to create uniform systems across the map.
If you are looking for USB upgrade software to get any USB up and operating on your pc, look no further than car owner upgrade software. Driver upgrade software also known as program upgrade software has the ability to to upgrade any USB application both quickly.http://topsoftwaretrading.com/
While I wouldn't have anything break itself to make a point I'd much rather have documentation than a standard API format. Lets form a new JSON API standard
Wow. No one needs this. API means application programming interface. It starts and ends its standardization at the application level.
Make your API consistent and write decent documentation for it. That's all anybody needs and will be simpler then trying to conform to some insane metastandard.
But my "fear" is that it will all get to complicated, too. Currently I really like to work with JSON Schema (http://json-schema.org/), because it's simple and extensible.
Does anyone know when we could expect Ember Data to be fully compatible to JSON API? In a stable manner.
Our architecture has Sinatra for the backend and Ember.js for the frontend. We're always in a struggle to support JSON API for our third party clients but maintain compatibility with Ember Data.
108 comments
[ 2.2 ms ] story [ 175 ms ] thread[1]: https://news.ycombinator.com/item?id=9280602
For example, RC2 mandated that all fields were dasherized. We made field names opaque in RC3.
At this point, we're pretty much nailing down tiny details and included this language with RC3:
https://en.wikipedia.org/wiki/Software_release_life_cycle#Re...
[1] https://github.com/jsog/jsog
My main issue was with the "related/linkage" stuff (which may or may not have changed somewhat since I was exposed to it), which is unpleasant, to my eyes, in the way it is expressed, and also verbose and often duplicative in what it produces.
A related problem was the Node.js implementation we were using, which generally felt like more of a hindrance than a help (and which we ended up extending beyond all recognition, making matters dramatically worse - though that was no fault of JSON API itself directly, other than by association).
Best of luck!
Here's the basic things that have been mostly useful:
The tagged-sums bit is probably a dealbreaker for me at this time: I picked this up from Haskell and I would not easily let go. The syntax in JSON is a little clumsy, but it's still important. Cf. Abelson and Sussman's lectures, "All interesting programs start with a case dispatch."[0] https://github.com/apotonick/roar
Edit: and hey, why not, I'm the author of a generic HAL client myself: https://github.com/deontologician/restnavigator
Consider the case of a blog. Each blog post has many comments. Each post has an author, and each comment has an author. Some of those entities may have dedicated URLs, and others may not. Additionally, the authors are highly repetitive; you want to refer to them by identifier, not by embedding them.
Because a tree of data can be represented easily as a graph, but not vice versa, JSON API provides a straight-forward way to provide a list of records that are linked to each other. The goal is simple, straight-forward processing regardless of the shape of the graph.
As an example, let's say that my graph DB has People nodes and a MARRIED_TO relationship between two people to indicate they are married. A MARRIED_TO edge could have a "married_on" property containing the date of the marriage.
Where would the "married_on" attribute be represented in JSON API? I could stuff it in the "meta" member of the link object, but that feels loose and hacky. Maybe it could live in the "linkage object" along with the "type" and "id" members. But the linkage object appears to currently be a closed set of only those two members.
Is this requirement to present a full property graph model not as common as I would imagine? I'm a bit behind on my sync with the current state of the spec. This is the first time I've tried to elaborate this need.
Most of the trouble in building a JSON API comes not from deciding on the format, but in nailing down the precise requests and responses that handle common kinds of interactions. This became very clear to me as I worked on Ember Data.
The good:
- It opens a path for standardized tooling among API clients. Rather than having a whole mess of JSON-over-HTTP clients with a hard-coded understanding of the particular API, one could theoretically use a hypertext client to interact with any API using this standard.
- It establishes a baseline of what an API server must implement.
The bad:
- It tries to control not just the media type, but the protocol (HTTP) and server implementation. This is problematic because it dictates how your server must implement its routes, and is tightly coupled with HTTP.
- It tries to be very prescriptive, but it cannot cover all edge cases without being exhaustive. This comes at a heavy burden for implementers to get every part of the specification correct. Despite this, some extremely basic features are missing, such as providing an index document so that a client can enter the API knowing only a single entry point (as it stands now, clients must have a priori knowledge of what resources exist on the server).
The ugly:
- Since so many parts of the base specification are optional MAYs, and there is no prescribed mechanism for feature detection, there is no way to figure out if a server supports a particular feature of this spec without trying to do something and failing.
- The spec has made many breaking changes on the road to 1.0 (as other commenters have mentioned, and there is still room for breaking changes).
At this point, I think that this project gained traction due to the clout of the original authors (Yehuda Katz and Steve Klabnik) and the promise of no-more-bikeshedding, though I would argue that the bikeshedding has just shifted from particular APIs to the spec. Disclosure: I authored and maintained some libraries that implement this spec, and authored another media type for hypertext APIs.
Some media types do consider their applicability over multiple protocols, for example: http://amundsen.com/blog/archives/1151
> The spec has made many breaking changes on the road to 1.0
Interestingly, most of the breaking changes on the road to 1.0 were about drastically reducing MAY in favor of MUSTs.
Optional features were moved to named extensions, and there is now an explicit way to negotiate about those extensions.
For anyone who was put off earlier on by the number of MAYs, know that we heard you loud and clear. It may (no pun intended) be worth another look.
Let me try to give some perspective on the history. For a long time, JSON API was more of a set of guidelines than a strict specification. A lot of our early adopters hated all of the MAYs in the spec (you can see examples of that throughout this thread), so we decided to tighten things up considerably towards the end of last year.
That meant trying to eliminate the vast majority of options in the primary spec, and moving all optional features to named extensions that clients could programmatically detect.
Of course, significantly tightening up the semantics forced us to grapple with harder problems and pushed some ambiguities into the light of day. RC2 in particular was an attempt to seriously pare down the scope of the main spec, while making the semantics of what was left stricter. Dan (the primary editor) and I spent countless hours discussing various details, and people contributed hundreds and hundreds of (very useful!) comments during this period about various details.
RC3 was a smaller delta, but I could easily imagine that one of the changes had a large impact on existing APIs.
My overall goal for the project from the beginning was to nail down a full protocol (both the format and the wire protocol) that could be implemented by multiple languages on both sides. Originally, it was created because I was frustrated by the ambiguity of "REST-style API" was during the development of Ember Data.
The earliest versions of JSON API didn't really nail things down well enough to deliver on that promise, but I hope that the latest versions will be able to. Time will tell.
One challenge with the churn is a lack of any high-level changelog (git commit history doesn't count). I have a team working off an earlier version of the spec, and I check back semi-frequently. But I haven't been able to find a document outlining "here are the major changes since the previous versions." I understand that would represent more work on top of work, but for such a large spec, the changes have been disorienting.
They keep saying that they're closing in on 1.0, but there's a few issues left:
https://github.com/json-api/json-api/issues?q=is%3Aopen+is%3...
They've been making a lot of changes lately:
https://github.com/json-api/json-api/graphs/contributors
It's good that they want to get all of the breaking changes done so that they can declare a stable 1.0. But it also seems like they're going to try and call it stable right after making a bunch of changes, which seems risky.
I also pitched JSON-LD/Hydra at work, because they're w3c-backed and JSON-LD has some uptake. But the other people who looked at those specs found them hard to digest. And I agree; as an implementer, I can read the jsonapi docs quickly and have a pretty clear idea of what to do. But with JSON-LD/Hydra, not so much.
I get the sense that JSON-LD/Hydra is more flexible than jsonapi, but I think jsonapi does what we need. And if it does what we need, then additional flexibility might actually be a drawback. I guess we'll see how it goes.
For what it's worth, the issues you linked to are mostly about adding more rigor to possibly underspecified areas, not changing things that are already specified, but those things could easily be done after 1.0.
About the only thing useful in the spec is a separate errors list so that I can easily check if it worked as it should.
Also there is apparently no way to authenticate so you either have to allow everybody to create/alter whatever on your server or nobody. Yikes.
If I get my way, whatever I work on will be tailored to break if the client assumes this "standard".
The result MUST be in JSON format.
Documentation of the API MUST exist.
Errors SHOULD change the HTTP code as appropriate
That is all.
Make your API consistent and write decent documentation for it. That's all anybody needs and will be simpler then trying to conform to some insane metastandard.
See http://de.slideshare.net/lanthaler/building-next-generation-...
But my "fear" is that it will all get to complicated, too. Currently I really like to work with JSON Schema (http://json-schema.org/), because it's simple and extensible.
No, thanks.