JSON API v1.0 review


#1

Hey all! @briankardell suggested I come here and post, so here I am!

I co-author a media type specification named ‘JSON API,’ and we’re about to finalize the spec. So I wanted to post it here for some feedback. We’ve been working on the draft for about a year, and there’s a bunch of deployments that already exist.

Thoughts?


#2

Man, there’s a lot to like there… The REST + PATCH stuff is really nice… I know that I have suffered through a lot of pain with unexpected twists and turns for a lot of this that differ from API to API even within the same company. Most of the spec seems like it is about explaining the particulars of how the HTTP/JSON/conceptual aspects work, but the examples section also lists client libraries. Seems to me that it would be good to separate them more as the later is less connected to what could make it valuable for many.

Do you think it is possible to create a test suite for the server side conformance? Seems like if you could somehow factor out the records it would be plausible to test pretty much any API, and more generic sorts of stores/services could benefit greatly… I’d love to see more interoperable implementations further on that page - maybe we can help expand it.


#3

Thanks!

know that I have suffered through a lot of pain with unexpected twists and turns for a lot of this that differ from API to API even within the same company.

Yes, this is what I want to kill. At least, as long as it’s a bikeshed, and not a good reason. I don’t think EVERY API should be JSON API, but most of them should be.

Seems to me that it would be good to separate them more as the later is less connected to what could make it valuable for many.

Yeah, someone else was a bit confused as to what was the ‘spec’ and what was metadata. I’m going to change ‘format’ to ‘spec’ to make this more clear.

Do you think it is possible to create a test suite for the server side conformance?

Maybe. I do have a partial JSON Schema that can test just response bodies…


#4

I have 3 questions which you may have dealt with in the past so maybe there are easy answers.

What does this provide that is better than OData?

http://odata.org

  • OASIS standard JSON format.
  • Proper metadata exchange protocol.

Why corrupt the object with a links attribute?

I don’t see how this adds any value? Why not simply use the attribute name as is. The fact that there is a root element called links already implies that there are relationships that can be discovered at specific resource addresses and the template gives enough information to pull these out of the object.

So instead of this:


{
  "links": {
    "posts.comments": "http://example.com/comments/{posts.comments}"
  },
  "posts": [{
    "id": "1",
    "title": "Rails is Omakase",
    "links": {
      "comments": [ "1", "2", "3", "4" ]
    }
  }]
}

Why not have this:


{
    "links": {
      "posts.comments": "http://example.com/comments/{posts.comments}"
    },
    "posts": [{
      "id": "1",
      "title": "Rails is Omakase",
      "comments": [ "1", "2", "3", "4" ]
    }]
}

Or even this:


{
  "links": {
    "posts.comments": "http://example.com/comments/{posts.comments.id}"
  },
  "posts": [{
    "id": "1",
    "title": "Rails is Omakase",
    "comments": [ 
	  { "id" : "1" , "title" : "Some title" }, 
	  { "id" : "2" },
	  { "id" : "3" }, 
	  { "id" : "4" } 
    ]
  }]
}

The second suggestion is not really appropriate for this use case but illustrates how the URL template can provide the path within the object that provides the value required to build the URL.

By using the links attribute your are telling the caller more about the underlying data model than they need to know and preventing yourself from changing this in future.

Why depend on the JSON Patch standard? It is so vastly different to the rest of your spec?

The JSON Patch standard is so different to the JSON API standard. You are now mixing operations into your data where the HTTP verbs should be enough. Examples from the spec:

Instead of:


PATCH /photos/1
Content-Type: application/json-patch+json
[
  { "op": "replace", "path": "/photos/0/src", "value": "http://example.com/hamster.png" }
]

use:


PATCH /photos/1
Content-Type: application/vnd.api+json
[
  { "src" : "http://example.com/hamster.png" }
]

Instead of:


PATCH /photos/1
Content-Type: application/json-patch+json
Accept: application/vnd.api+json
[
  { "op": "replace", "path": "/photos/0/links/author", "value": "2" }
]

use:


PATCH /photos/1/  <-- dropped the "link" part. See comment above.
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
[
  { "author": "2" }
]

Instead of:


PATCH /photos/1
[
  { "op": "add", "path": "/photos/0/links/comments/-", "value": "30" }
]

use:


POST /photos/1/comments
[ 
  "30" 
]

Instead of:


PATCH /photos/1
[
  { "op": "remove", "path": "/photos/0/links/comments/5" }
]

use:


DELETE /photos/1/comments
[ 
  "5" 
]

#5

Nice work!! What is really nice is the organization and the clear way of representing linked resources.


#6

Further clarification of what errors can contain would be brilliant; something I would like to see is a per attribute set of issues - that way form validation could be done over the JSON API.

With that as an idea it would be nice to be able to request a ‘validation’ operation which has no side effects on the server side.


#7

This is quite interesting, thanks for bring it here.

A few random questions:

Why make PATCH support optional? Optional things are annoying for developers, you have to test/branch for them. I would expect something like this to benefit from a bunch of easy-to-deploy modules to both interact with it and create endpoints. Reducing optionality would help.

Are you sure that a new MIME type is necessary? I don’t get the impression that it brings much to the table, and if you want to make it clear that a service is “JSON API” happy, then you could expose that as a well-known endpoint or some such.

I wonder if you’ve looked at http://www.w3.org/TR/html-json-forms/?


#8

What does this provide that is better than OData?

This is not trying to be semantic web style. I know OData people don’t like being compared to the semantic web, but from my vantage point, they’re very similar.

Why corrupt the object with a links attribute?

Because objects can be linked to other objects. A response can contain more than one kind of object, so the top level isn’t always appropriate.

Why depend on the JSON Patch standard

Because HTTP PATCH needs a ‘diff media type,’ and JSON Patch is the best supported one.


#9

With that as an idea it would be nice to be able to request a ’validation’ operation which has no side effects on the server side.

Oh yeah, this would be interesting.


#10

Why make PATCH support optional? Optional things are annoying for developers, you have to test/branch for them. I would expect something like this to benefit from a bunch of easy-to-deploy modules to both interact with it and create endpoints. Reducing optionality would help.

Alternatively, optional-ness means that a wider variety of servers are acceptable, which historically has worked well on the web. You’re not required to support everything that’s optional.

Are you sure that a new MIME type is necessary?

Absolutely. The ‘stateless’ REST contstraint that HTTP follows says that a client is supposed to be able to interpret a response without any additional context. application/json does not have an extensibility mechanism, nor any of the features we’ve added on top of it.

I wonder if you’ve looked at http://www.w3.org/TR/html-json-forms/?

I vaguely remember maybe looking at it once?


#11

You answered all of my questions without actually providing any answers :smile:

So why would I choose to write an API that abides by the JSON API standard if I can just write one that abodes by OData standards? My clients can find free OData client libraries on the web today why make them write this from scratch?

But now my objects can’t have members called “links”? If my data model represents a blog post that has a property “links” and this represents a set of URLs I have to make up an alias for that property. Reserved member names are a bad idea in general.

I still see no compelling reason to move the linked objects from the top-level.

Sorry but I still see this as massively over-complicating what should be a simple procedure. Is there a use case where my suggested approaches to PATCH would not work?


#12

Sorry about that :[ Let’s try again:

So why would I choose to write an API that abides by the JSON API standard if I can just write one that abodes by OData standards?

Oh, sorry. I see the semantic web as being overly complicated and basically a complete failure. It is hard enough to get people to be convinced to add a link or two to their responses, let alone generate ontologies. Furthermore, I have philosophical beef with the entire notion of the semnatic web. I don’t want to distract this discussion with that, however.

You are correct that tooling already exists for OData. Use it if you like OData. No big deal. “One Format to Win Them All” is a fallacy, as far as I’m concerned.

But now my objects can’t have members called “links”? If my data model represents a blog post that has a property “links” and this represents a set of URLs I have to make up an alias for that property.

Yup. We have five reserved words, and most of them are pretty obscure / used for what people use them for already. It’s a tradeoff.

Sorry but I still see this as massively over-complicating what should be a simple procedure. Is there a use case where my suggested approaches to PATCH would not work?

This is your critique of me not using OData, but in reverse. Why re-build something that already exists? Diffs are actually really hard.


#13

Thanks! Some things to ponder on.

A general comment on standardisation which is pertinent, I think.

Your motivation for a new approach to solving the problem OData solves is that you have a philosophical beef with a notion that you believe underpins the approach OData takes. So instead of discarding OData entirely why not attack the issues you have with it, or its approach?

I agree, there isn’t one format to win them all but ultimately shouldn’t we all be striving for that?

There is only one HTTP, and only one HTML. There are variations, adjustments, iterations etc but ultimately theses technologies evolved as standards because the contributors were more interested in solving the problem than their personal beef with some philosophical notion.

http://xkcd.com/927/

Personally, I disagree that OData has anything to do with the semantic web but that’s also a discussion for another day.

I’d be interested to know what use cases you are covering with JSON API that are not covered by OData?


#14

@ahopebailie - Let me add an alternative view: All of the technologies you’re talking about were actually very similar to this case initially and, in my estimation, their competitors were more entrenched than oData. Gopher predates HTTP, it had an IETF RFC, and was widely used. SGML predates HTML by decades and was very widely deployed - it is in many ways superior to HTML and, in fact, has technical answers for things that after 2.5 decades HTML still hasn’t. JSON came about after XML was a standard and had nearly every possible advantage. Sometimes there are technical reasons, sometimes it is simple ergonomics that catch on with developers, etc. What matters at the end of the day is for developers to choose something. If OData doesn’t resonate with folks (and it doesn’t with a lot of us) it’s reasonable to spec out an alternative and see what catches on. It’s entirely possible that they will both become better for it as they compete - or that one will die off. What we have now with HTML and HTTP is widely deployed and interoperable on an unprecedented scale, they are in a way ‘special cases’ - very hard to supplant, intertwined in the deployment of browsers - considerably more pragmatic to focus on evolution and cooperation, but variation and competition at the stage of something like OData is actually especially healthy IMO… Even if they covered only the same exact cases, ergonomics and uptake are very important.


#15

@briankardell - I agree with most of what you say above. I am simply playing devil’s advocate which I think is essential to any standards development process. The alternative is a group of people patting each other on the back telling one another that what they are doing is better than anything else out there.

My questions are not intended to suggest that the writers of the JSON API spec should simply give up but to encourage them to consider what else is out there and have clear ideas about why they are building something new instead of extending something that has already been through all of the difficult twists and turns to become a ratified standard.


#16

Yeah I came here from googling json api vs OData

I don’t know or care about more abstract proxy comparisons such as whether or not it’s rooted in semantic web. However I’m very interested in concrete plusses and minuses for each format. True that JSON is now beating XML, at least in some areas, but those advocating JSON were able to articulate why it was better. They didn’t just point to history and say that “sometimes things supercede other things.”

Why is it better?