GithubHelp home page GithubHelp logo

json-api / json-api Goto Github PK

View Code? Open in Web Editor NEW
7.3K 7.3K 826.0 2.9 MB

A specification for building JSON APIs

Home Page: https://jsonapi.org

License: Creative Commons Zero v1.0 Universal

Ruby 0.45% HTML 7.98% JavaScript 35.46% CSS 45.21% Makefile 2.13% Python 2.96% Shell 0.17% Groovy 0.50% Scheme 0.23% Sass 3.53% SCSS 1.38%

json-api's Introduction

JSON:API

Documentation for the application/vnd.api+json media type, a specification for APIs that use JSON. This repository is the source code for http://jsonapi.org.

Resources

Status

This standard is currently under development. To assist:

  1. Get the dependencies:

    $ bundle

  2. Host the site locally while editing:

    $ bundle exec rake preview:browser

  3. Edit the Markdown files.

  4. Commit your changes.

  5. Send a Pull Request when finished.

The website is automatically built by GitHub Pages when changes are pushed to the gh-pages branch.

Archive

older versions of the JSON:API documentations

json-api's People

Contributors

andrewsardone avatar bacarini avatar beauby avatar bf4 avatar bintoro avatar bobholt avatar brixen avatar codingitwrong avatar cziegenberg avatar dgeb avatar diosney avatar ethanresnick avatar freddrake avatar gabesullice avatar hhware avatar jede avatar jelhan avatar jfinkels avatar kjg avatar kocsismate avatar lgebhardt avatar lode avatar masterspambot avatar mickeyn avatar spastorino avatar steveklabnik avatar tiagopog avatar vfaronov avatar wvteijlingen avatar wycats avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json-api's Issues

PATCH and resource versioning

How does JSON API handle or indicate conflicts when multiple clients simultaneously attempt to modify a resource?

Primary keys that aren't id and composite primary key support?

While Rails "restful routes" (quotes != sarcasm, just mean that is what they are called) use the single id convention in paths, is it really ok to make the assumption that everything using this media type will pass a composite key this way vs. a different route to get the resource? i.e. in it gives the example:

In the above example, a GET request to /posts/1/comments returns a document containing the four specified comments.

Examples of requests, etc. similarly show a single integer as the id, e.g. "id": "1", and it is referred to as a singular entity named "id".

So, how would a composite key work?

Also, I read:

Each document in the list MAY contain an id key.

IDs

The "id" key in a document represents a unique identifier for the document, scoped to the document's type. It can be used with URL templates to fetch related records, as described below.

Attributes

Other than the "rels" and "id" keys, every key in a document represents an attribute. An attribute's value may be any JSON value.

Rails has historically allowed set_primary_key= and later self.primary_key= to set an alternate primary key (or keys as an array (iirc) in the case of https://github.com/drnic/composite_primary_keys).

In the case where the id is not id and/or perhaps id is not the id but is still a valid field, how should that be handled? Or must the primary key (singular only) be sent as "id"?

Mostly just curious, because we have both composite keys and non-standard id column names.

No need to couple REST and Entity Concerns

This issue will also probably get a lot of hate. Enjoy.

Seems like this spec is doing two things, when in practice it would be better if it did one thing well. This is defining how to use REST (response codes, urls, etc); plus how json entities for the objects should be defined.

REST has already been defined (and if it hasn't been clearly spec'ed out, which I'd be surprised, maybe we should make a clear spec for that as well). By coupling the two ideas it becomes a little less flexible.

Say we want to store a json-api format entity (meta, etc) in memcache. Saying it was a "json-api" json object wouldn't really make sense, because the post data wouldn't be there. Also I don't see a reason why someone couldn't use entity format across a non-RESTful API; could be useful in a binary protocol api or something.

Just my 2 cents. Feedback welcome, haters.

URI generation from ids should be stateless and uniform for discoverability

Currently, in order for a client to generate a URI based on the "ID Style" specification, the client would need to discover and statefully maintain the out-of-band knowledge required to generate the URIs specific to that API. To quote the current specification language, emphasis mine:

"A base URL that represents the type of the related resource (this must be hardcoded in the client).

In the example given for "To-one relationships", the mapping between "author" and "people" is out-of-band knowledge that significantly reduces the discoverability and programmability of an API in the "ID Style" (and seems at odds with the intentions of the RESTful design and hypermedia in particular).

(As an aside, I would suggest that the "ID Style" of API is at best only a pseudo-hypermedia format and is mainly useful as a transitional step between plain JSON and "real" hypermedia formats. Perhaps the specification could call this out to better manage expectations. I suspect that a minimum viable hypermedia format involves at least URI templates.)

In order to allow "dumb" clients to programmatically access the API by traversing hypermedia links between resources, the heuristic used to generate URIs from ids should be uniform (the same across all compliant implementations of the spec) and stateless or minimally stateful (requiring a minimum amount of out-of-band information to generate the URIs). And example of such a heuristic follows, with the significant change highlighted:


To-many Relationships

  • A base URL that represents the type of the related resource. This is defined as the plural form of the related resource; in this case, authors.
  • ?ids=
  • A comma-separated list of the specified IDs

If the location of the resource is actually at the "people" endpoint then this knowledge can be transfered to the client in-band via a permanent redirect.

PATCH definition is not RFC compliant

Sorry if I'm duplicating existing question.

What I talking about is the reference on the page http://jsonapi.org/write/#toc_updating-a-document-code-patch-code to JSON Patch draft document. Link on JSON Patch is leading to outdated version of document.

If you look at latest version (http://tools.ietf.org/html/rfc6902#section-4) of proposal, you will see major change in format:

{ "add": "foo", "path": "/a/b/c" } # outdated version
{ "op": "add", "path": "/a/b/c", "value": "foo" } # latest version

Should it be updated? I could make PR if needed.

URL templates in global `links` can use non-relationship fields, and can omit related IDs in per-object `links`?

I think the reading document has changed such that a use case that was there is now missing, and I want to make sure this is still supported...

Will the spec allow the following payload (or something very similar):

{
  "links": {
    "posts.comments": {
      "href": "http://example.com/posts/{posts.id}/comments",
      "type": "comments"
    }
  }
  "posts": [{
    "id": "1",
    "title": "Rails is Omakase",
   }, {
    "id": "2",
    "title": "The Parley Letter",
   }, {
    "id": "1",
    "title": "Dependency Injection is Not a Virtue",
  }]
}

The two key elements here are:

  1. The href key uses a non-relationship value.
  2. The list of IDs for the relationship is omitted from the object.

The second constraint is particularly crucial, because to include a list of all IDs connected to an object can be expensive both computationally and bandwidth-wise. Just as the most basic example, at the linked URL we could implement paging but as far as I'm aware there's no way to have a "paged" array of IDs representing the relationship. E.g., consider a category with 1000+ items.

Please tell me this will be allowed. Forgive me if this has been discussed, if so I missed it.

Requesting includes

The reading document mentions that it's possible to pack all of the relation's exploded data into a single file, but doesn't discuss whether it's possible for the client to request includes along with the top-level objects. This is a very common pattern across many APIs, especially those in the style of eg Facebook or LinkedIn, where individual fields and associations can be requested as part of the top-level request.

Statically-Typed Keys

The ambiguity around the type of the keys (namely, that they can be either single objects or an array of objects) presents a problem for most statically-typed languages. For example, in Android, I always build deserialization right into the network request layer. As part of this, I build a generic "Response" class that the JSON is deserialized into. I can then interact with that Response class to obtain the data in a statically typed way, which ensures type-safety within the application itself.

While this project is geared towards Javascript applications, I can't build an API against a schema I know won't play well with mobile or other clients I may write. So I think this is an issue worth resolving.

I have two proposals for a solution:

We can use plurality to separate between types; e.g., a single post could be returned as:

{
  "post": {
    "id": 1
  }
}

and multiple posts could be returned as:

{
  "posts": [
    { "id": 1 }, { "id": 2 }
  ]
}

The problem with this is that clients now have two places to look for the content they're expecting (if I GET /posts and it only returns one post, should that be in "post" or "posts"?) and the vagaries of pluralisation are now an API concern.

The alternative proposal (which is what I use in my APIs) is to never return a bare object. Whether one post or one hundred posts are returned, it is always under the "posts" key, and it is always in an array:

{
  "posts": [
    { "id": 1 }
  ]
}

This allows for type-safety by the simple addition of two characters to the response. It always locates the content under the same key, regardless of any other conditions. And it adds no new overhead or meaning to keys. The only drawback is that there is a slight cognitive dissonance around asking for one resource ( GET /posts/1) and receiving a list in response. I would argue, though, that semantically this response is correct: the user is not requesting the post object itself, the user is requesting a response object containing the post object--which is why it's semantically permissible to include the metadata and errors in the response, as well.

Polymorphic types

At @balanced, we have an endpoint, transactions, that returns polymorphic types of Credit, Debit, Hold, Refund, and Reversal . The transactions endpoint returns these objects in order of creation.

How would the payload structure look like?

{
   'transactions': [
       {
          'debit': {
               'id': 'WDxxxxx',
               'uri': '/v1/holds/WDxxxxx',
               'created_at': '2013-04-02',
          },
       },
       {
          'hold': {
               'id': 'HLxxxxx',
               'uri': '/v1/holds/HLxxxxx',
               'created_at': '2013-04-01',
          },
       },
   ]
}

Is this the right way?

Feedback and Thoughts

This issue was opened by @ghempton on the defunct https://github.com/emberjs/jsonapi. I've migrated it here.


Stumbled across this document for the first time today and wanted to start a discussion around some perceived missing features of this protocol. If we are going to commit to a data transfer format that is intended to be "A generic protocol that can work across a broad set of use cases, including the generally used relationship types", I hope the following cases will be considered:

Sync Semantics and Deletion

I understand that there is a desire for this protocol to be "REST-style". In that light, the notion of passively communicating (read "sideloading") deletions and other operations feels a bit foreign, however I think it is very necessary. For a long running client-side application to function correctly, it will need to stay in sync with the server; its state cannot be purely a reflection of the RESTful actions that it has taken.

In the case of delete, depending on the backend, there can be some ambiguity as to what deleted documents should be sent to the client. Surely the client should not be aware of all models on the server. In most cases, I think that it is enough to only send down deletions that are relevant to that request: e.g. a DELETE request to a "group_member" document could potentially result in its parent "group" document being deleted in certain cases.

Taken a step further, it might be necessary for the protocol to handle the server sending down compound documents that contain "operations" in addition to related documents. This could be used to preserve intent (OT) in the case of conflicts. Maybe this could use a similar convention as PATCH?

I suppose this could just use the meta key:

"meta": {
    "deleted": {
       "comments": [ 5, 12, 17, 20 ]
    }
},

But I feel that it should have first-class support within the specification.

Non-CRUD Verbs

I feel that in any non-trivial application, it is an extremely tall order for all the business logic pertaining to a model to be handled by CRUD operators. Are there any thoughts around support non-CRUD verbs?

Polymorphic relations

There are two interesting and/or tricky relationships I can think of immediately that don't seem to have been covered yet:

  1. Name-aliased relationships, like when a post has an author that is actually a user object. This is semi-covered in the URL style, but there are unanswered questions like how the client is supposed to know to look in the "users" JSON key for the post's author_id.
  2. True polymorphic associations, where a post's authors might include both users and companies. Since neither one of those can be exploded into an "authors" key, how do you distinguish user ID 1 from company ID 1?

Improve jsonapi.org by bit more descriptive abstract

When reading the abstract for the first time, I was not quite sure what the project was about: what are the goals for example. Abstract makes more sense once you learn the basics.
So it would be good to cover bit more of the basics first; otherwise it is easy to get "wtf?" reaction. :)

Description of API styles would also benefit from links to more authoritative sources, since it is not clear whether two styles are widely considered to be canonical JSON API interfaces (which seems to be the implication), or just examples of commonly seen ways.
To me latter seems more likely explanation, but text as is would suggest former.

Representing embedded resources?

Is the following example valid?

{
  "rels": {
    "authors.photo": "http://example.com/people/{photos.author}/photos/{photo.id}"
  },
  "authors": {
    "id": 1,
    "href": "http://example.com/people/1",
    "title": "Tom Dale",
    "rels": {
      "photos": [1]
    }
  },
  "photos": {
    "id": 1,
    "href": "http://example.com/people/1/photos/1",
    "title": "Hamster",
    "src": "images/hamster.png",
    "rels": {
      "comments": [ 1, 5, 12, 17 ],
      "authors": 1
    }
  }
}

I'm specifically worried about embedded documents that can only be accessed via their parent document (eg Mongoid's embedded relationships) but this would seem relevant to Rails' embedded resources also.

id always as a string?

Most of the examples use integers to represent ids. ids should be opaque, a token that we use to check for equality and we don't need an order relation between ids.

Integers smell like auto-increment ids but that won't always be the implementation server-side. Seems like strings are a more flexible and sane way of encoding any type used server-side as the primary key.

Client-side generated ids are often uuids, which are most commonly represented as strings. Also, ids will be part of URL and used in URL templates. With strings we won't need to convert the ids back and forth between two types.

I think that strings are more suitable for the job. Thoughts?

Related: note some inconsistencies between the type of different ids in this example:

{
  "posts": {
    "id": "1",
    "title": "Rails is Omakase",
    "rels": {
      "author": 9
    }
  },
  "people": [{
    "id": "9",
    "name": "@d2h"
  }]
}

Hash instead of array

Why not to use hash instead of array?

{
  "posts": {
    "1": {"title": "Rails is Omakase"},
    "2": {"title": "The Parley Letter"}
  }
}

instead of this:

{
  "posts": [{
    "id": "1",
    "title": "Rails is Omakase"
  }, {
    "id": "2",
    "title": "The Parley Letter"
  }]
}

Name of the Spec Will Ensure Confusion

I feel like this is going to get a lot of hate; but I'm going to post it anyway.

If this specification is to take off and become the defacto-standard I think it's name will cause a lot of confusion when communicating about API's as it will not be clear what is actually meant by "This is a json-api". Does the documentation mean it follows this spec, or just a confused developer talking about a regular json api and they actually have no idea what they're talking about. Was the hyphen just a typo? Who knows?

I think we assume that people will be on our level whose API's we consume, but I've worked with API's (out of necessity not choice), from developers who kind of get stuff but are seriously missing some key aspects.

Two examples of people sort of getting it that I can pull of the top of my head.

API 1: XML Based API

The developer built an API with the server built in dot net. I was consuming the API in Ruby or Java, or something without the native auto-wiring abilities. Dot-net hooked up the web service with XML in a certain format automatically: which exposed it with xml headers, and xml response body in separate fields in the xml.

The developer read up on how the API's were built, and knew that the request was supposed to follow that convention, so in the "response" xml bit, they rebuilt a new response, wrapped in the containing xml. It resulted in an XML request, embedded as a string inside a separate xml request.

I convinced myself when integrating with this API it was built by xzibit. Yo dawg, I heard you like xml, so I put some xml in your xml so you can parse while you parse. I'm excited about the opportunity to reuse that joke.

API 2: Proper use of HTTP Codes

The developer knew that using the proper HTTP codes in responses was important. So the response code was embedded in the json response. Some examples:

HTTP: 200 OK
Response:
{
"status":200,
"body": "omg"
}

HTTP: 200 OK
Response:
{
"status": 404,
"body": "not found"
}

Calling this the "json-api" schema will ensure that confusion about whether or not the json follows this spec, or just is an api that returns json with many developers.

I also find it a little misleading, as there are other completely reasonable JSON API formats. See #50. Technically most of those are "json api" specs as well.

To draw a comparison of a similar topic, take REST. If someone says their API is a RESTful one it is immediately clear that when it comes to "REST" they get it.

But what if it was named a little differently. REST is basically just "let's use HTTP requests the way that the HTTP spec was defined". Following the same convention REST could've been called "HTTP". "Yeah bro, I'm integrating with this HTTP-api". Would that dude mean a REST api, or just an API that goes over HTTP, like API example number 2. Who knows?

Just my 2 cents.

Requesting fields

Some objects have fields that are either large (like associated binary data) or expensive to calculate. Is there a conventional way to request optional fields, or limit the response to only fields that are relevant to the client?

History page

The fact that we start with history is making some people think this is ember/rails specific, when the entire purpose is to make it not so.

POST array when creating?

When we GET a resource, we always want an array. Should we do the same for POST?

Take the first example from write.md:

POST /photos
Content-Type: application/json
Accept: application/json

{
  "photos": {
    "title": "Ember Hamster",
    "src": "http://example.com/images/productivity.png"
  }
}

The plural key photos doesn't make sense here unless we pass an array. It would make sense to either change the key to photo, or even better and easier, just require that we POST an array:

POST /photos
Content-Type: application/json
Accept: application/json

{
  "photos": [{
    "title": "Ember Hamster",
    "src": "http://example.com/images/productivity.png"
  }]
}

This also allows us to create multiple photos in one request if we wanted to:

POST /photos
Content-Type: application/json
Accept: application/json

{
  "photos": [{
    "title": "Ember Hamster",
    "src": "http://example.com/images/productivity.png"
  },{
    "title": "Angular A Badge",
    "src": "http://example.com/images/boring.png"
  }]
}

What are your thoughts?

The term "rel" is being used in a different way than the HTML spec

In the HTML4 spec and HTML5.1 draft the rel attribute is used to specify the "role" of a link. In the current JSON-API spec, however, it is used to specify the links themselves. I think this mixing of metaphors may be confusing to some people (myself included).

I would suggest instead using refs, which maps to HTML's use of the href attribute, or links as used by HAL.

This would also preserve rel for more idiomatic uses, for example an "extended" reference specification:

{
  refs: [{
    rel: 'next',
    ref: 'http://example.com/pages/2'
  }]
}

FAQ page

Lots of people asking questions on a few topics:

  1. Caching
  2. Pagination
  3. versioning

We also need to address other specs that we work with; it's not immediately obvious to people that pagination is outside of this spec, since you'd use the standard relations or just define your own.

Update examples to include Accept header

It would be possible that a given service implements two or more different representations. Shouldn't the request include the header Accept: application/json?

Requesting filters or conditions

Okay, last one that immediately jumps out at me: in order to filter or limit the data that will be returned by some criteria, Rails has scopes and SQL has WHERE. Will there be a (presumably optional) section of the specification that provides a convention for clients that want, say, only the open issues on a specific repo, and none of the closed ones? Or only the draft posts, and none of the posted ones?

Singular vs Plural Resources

I'd like to discuss the use of the plural form of a resource name, regardless of whether a single object or an array of objects is returned.

For example, a single post is to be returned as posts:

{
  "posts": {
    // an individual post document
  }
}

Just like an array of resources:

{
  "posts": [{
    // an individual post document
  }, {
    // an individual post document
  }]
}

I can see some advantages to this approach:

  • it ensures that a single record won't be included twice (e.g. as a post and as a member of posts)
  • it may reduce the needs for an inflector in the client (although model names are often singularized, in which case singular/plural translations are still needed)
  • it makes the client leaner by eliminating the need to check both singular/plural forms of the noun

The disadvantages I see:

  • it is arguably semantically incorrect to return a single object with a plural key
  • it breaks with the conventions in stock Rails, AMS and most REST APIs I've encountered

It would be good to discuss this further and clarify the rationale in the spec.

Escaping scheme for ids with commas in them

If an ID is a string, and the string ID has a comma, how should the id string be represented in a comma-separated list of ids (e.g. in a URL request /comments?ids=5,12,17,20)? Or should this be expressly forbidden by the spec?

I know doing this would probably be poor design, but I'm trying to implement a .Net library that makes it easy to build a .Net MVC WebAPI backend that is JSONAPI compliant, so I thought I should consider this as an edge case.

URL length limitations

I'm a bit concerned about this requirement in the proposed standard:

An API that provides a to-many relationship as an array of IDs MUST respond to a GET request with a list of the specified documents with a URL formed by joining:

A base URL that represents the type of the related resource (this must be hardcoded in the client)
?ids=
A comma-separated list of the specified IDs

In the above example, a GET request to /comments?ids=5,12,17,20 returns a document containing the four specified comments.

My applications use UUIDs as the ID, so each consumes (with the comma) 37 characters in the URL. Many servers appear to have pretty severe limits to URL length. If, for example, the limit is 2000 characters, then my associated objects would be limited to no more than 54. How would I handle a case where I need to load 100 or even 1000 associated objects?

I don't have a workaround for this -- GET is clearly the right method here -- but I'm wondering if anyone has given this any thought.

Requesting sorting

Crap. I lied. Sorry. I was reading #8, specifically the bits about determining the canonical request object in the response (which is especially thorny since responses could include associations of the same object type). @paddyforan suggested that the response always be an array, but the canonical object always be the first object in an array. This brings up another question -- can clients request a sorting criteria? Sometimes sorting the objects is fast (or free) for the server, and so it might make sense for the client to request a particular sorting order or criteria. Worth adding a canonical example?

Select a mascot

To best promote JSON API as a universal standard across the universe, a mascot is vital.

To submit a candidate for the JSON API mascot, please comment with a link to visual artifact suitable for high quality print or display. By submitting, you assert that you own the copyright to the material (or it is in the public domain) and you release all rights to it with respect to its use by JSON API.

Submissions will be accepted until the standard is finalized for version 1.0, then a vote will be held.

Polymorphism

Should polymorphism be part of the API or leave it to the implementer.

Is it really a media type and how are requests identified as the format defined by the spec?

A media type for APIs that serve JSON.

This is using the application/json media type (mime type), so is it really a media type?

In http://jsonapi.org/write/ it states:

Creating a Document

A JSON API document is created by making a POST request to the URL that represents a collection of documents that the new document should belong to.

In general, this is a collection scoped to the type of document.

The request MUST contain a Content-Type header whose value is application/json. It MUST also include application/json as the only or highest quality factor.

So, if the incoming request is not defining it as the format defined by this request, what is in the request body, url, or headers that identifies the format of the request that the server should expect?

Also, what about versioning of the spec and how that is relayed?

Requesting resource that includes self-referential compound documents

Say each person has friends that are also other people. If I GET /person/1, and I'm returned a compound document, I'll get something like this:

{
  "people": [
    {
      "id": "1",
      "name": "Tammer",
      "links": { "friends": ["9"] }
    }, 
    {
      "id": "9",
      "name": "DHH"
    }
  ]
}

I can no longer assume that the first document in the "people" array is the one I want. I must instead loop through them comparing id values to get the root document I originally requested. Two solutions come to mind:

  1. Require an order, so that it's assumed that requesting a singular resource will return an array where the first document is that resource. I don't care much for this solution.
  2. Nest all related resources in another array. Fairly heavy handed:
{
  "people": [{
    "id": "1",
    "name": "Tammer",
    "links": { "friends": ["9"] }
  }],
  "linked": [
    "people": [{
      "id": "9",
      "name": "DHH"
    }]
  ]
}

This affects all responses, of course:

{
  "posts": [{
    "id": "1",
    "title": "Rails is Omakase",
    "links": {
      "author": "9"
    }
  }],
  "linked": [
    "people": [{
      "id": "9",
      "name": "@d2h"
    }]
  ]
}

...and begs the question of what to return if I am my own friend.

So: Thoughts?

Consider relaxing some MUSTs

One from HN:

That's great to hear. One particular example which I found needlessly strict is this:

    The request MUST contain a Content-Type header whose value is
    application/json.  It MUST also include application/json as the only or
    highest quality factor.

It makes sense for fully compliant implementation to have those headers, but they way I understand MUST here is that a server would reject any request without them.

https://news.ycombinator.com/item?id=5656097

Why not build on top of...

There are lots of these that make sense for an FAQ. A few pieces I'd like to include in that list.

JSON Schema (and Hyper-Schema)

"Describes your existing data format in clear, human- and machine-readable documentation which allows for complete structural validation to enable automated testing and validating client-submitted data."

JSON Ref

JSON Pointer

Swagger

JSON API spec is not versioned

The JSON API spec itself needs version information. When one of those mythical changes for which the current spec needs "flexibility", the version would be changed.

Plural and Sigular in URL template

Some examples use the singular in the URI template, but link to the plural form in the json keys. I may be un-usable for a robot, especially if the API is not using English.
It also seems an un-needed requirements as in the hypermedia model, you don't have to "understand" the URLs (the server will provide them).

Expected : Use plural or singular, but the key and the name in the URL template should us the same value

{
  "rels": {
    "posts.comments": "http://example.com/posts/{*post*.id}/comments"
  },
  "*post*s": [{
    "id": "1",
    "title": "Rails is Omakase"
  }, {
    "id": "2",
    "title": "The Parley Letter"
  }]
}

Extending profiles for filters, sorting, paging, ranges, etc.

To start off, I need to describe what we have already; we have a set of URL conventions used in: https://github.com/rubyservices/restful_json including (though there are others):

filter:

https://example.org/foobars?foo_id=123

filter greater than:

https://example.org/foobars?bar_date!gt=2012-08-08

filter greater than and return record count:

https://example.org/foobars?bar_date!gt=2012-08-08&count=

filter on "named attribute" (not a real resource field- represents a field of a direct or indirect relation defined server-side) and return unique (distinct) records:

https://example.org/foobars?and_one_more=an_attribute_value_on_my_assocs_assocs_assoc&uniq=

using the server-defined page size, return page count:

https://example.org/foobars?page_count=

return page at specific number, using server-determined page size:

https://example.org/foobars?page=1

range/more flexible paging:

https://example.org/foobars?skip=30&take=15

There are good reasons not to try to promote generalized querying for a variety of security and performance reasons, which is why we try to only provide each ability of the controller when the developer enabled that feature.

These are common relational DB concepts, so when each is enabled, it would be nice to have a standard agreed upon way of constructing a URL like used in that project. The ARel syntax used may not be optimal and could conflict with attribute/column names and require work in the model layer in those rare cases, but it works as a first cut.

The following http://jsonapi.org/extending/ provides an example for paging and it sounds like more examples of metas/profiles for the spec are under construction.

So, some questions:

  1. Is there going to be an official list of methods for defining a common subset of all of the extensions (profiles) as suggestions? It would be great to get people to agree on filtering, etc. similar to what we have above or to change our framework to work like some agreed-upon spec. They aren't going to keep adding them all to section 5 of RFC 6906. i.e. should there be a place to list common profiles/meta URLs, and how would that be administered?
  2. How do we avoid bloat of N metas/profiles in each response? Should things like all of the above features (filtering, paging, etc.) be a single profile URL (a group) or individual meta URLs?
  3. Is there going to be a suggested best practice for profile URLs to contain a version number in the profile URL? Could it be suggested to allow rational versions and suggest that client and server frameworks support partial matching of those versions, similar to gem versioning?: http://docs.rubygems.org/read/chapter/7 That way, enhanced versions of profiles could be provided where the URL of the profile changes, but the client could know that what they are doing is still compatibile, e.g.:

The client originally was developed to work with v1.2.3 of the profile http://api.example.com/simple-querying which came back at the time with:

{
  "meta": {
    "profile": "http://api.example.com/simple-querying?v=1.2.3"
  },
  ...
}

But later the API is changed slightly to fix a bug in a way that is still compatible with v1.2 of the API, so it returns the profile http://api.example.com/simple-querying?v=1.2.4 (perhaps some gem being used on the Rails server-side was updated). The client could continue to work without changes since it will continue to function as before for any version that starts with 1.2. This version potentially could even be the gem version itself that implements that functionality.

In summary, I'm wondering if (1) supporting extension for querying, etc. such as I've described above will bloat the response with profile URLs in the meta section, (2) whether there will be centralized administration to suggest commonly used profiles (like those used for querying as mentioned above, or perhaps some other standard for it), and (3) whether a rational profile versioning policy for profiles should be explicitly stated in the spec.

Thanks!

Meta-information for multiple resources

The meta key is currently defined as meta-information about a resource, such as pagination.

This seems limiting in cases where we want to return meta information about multiple resources. A couple of possibilities:

  1. Extend the definition of meta to possibly include meta-information about multiple resources
  2. Allow meta elements per resource

I've implemented 2 in RestPack, compound documents include resource prefixed meta elements such as artists_meta, albums_meta and songs_meta:

http://restpack-serializer-sample.herokuapp.com/albums.json?artist_ids=2,3&includes=artists,songs

@wycats also mentioned the possibility of 'meta everywhere' on the HN thread:

https://news.ycombinator.com/item?id=5655327

Sideloading?

Do we need something like this in the spec directly?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.