spine/spine — pull request #540 by richard-flosi (2014-05-20 22:57:45+00:00)
Title: HATEOAS Integration: Adding Model.root & Model.getObjects() hook.

Used in `Model.fromJSON()` and `Model.prototype.refresh()` to pick off a root data attribute from the server response.

In order to more easily accommodate HATEOAS APIs like [Tastypie](https://django-tastypie.readthedocs.org/en/latest/interacting.html#getting-a-collection-of-resources) which returns an object for collection requests (instead of an array) with a known root data attribute which contains the array, this pull request checks if `Model.root` was set and if so uses the value in `Model.root` to extract the desired data point from the server response.

In my case we have an API that always returns a response like: `{meta: {}, data: [], errors: []}` or `{meta: {}, data: {}, errors: []}` and I set `Model.root = 'data'` with this hook and can now use the default `fromJSON()` method with my API.

Likewise our API returns the `data` root attribute for detail responses and responses for `GET`, `POST`, and `PUT` requests. I was surprised to find that the responses for `PUT` were not run through `fromJSON` which is why I had to add the call to `getObjects` in `refresh`.

Related but only an issue with older browsers is the "JSON Array Information Disclosure Vulnerability" with returning an array that is not wrapped in an object:
http://stackoverflow.com/questions/16289894/is-json-hijacking-still-an-issue-in-modern-browsers

This Pull Request does not change any existing functionality and is an *opt-in* feature by setting `Model.root`.

----

The general problem I'm trying to address here is having an easy way to override the default `Model.fromJSON` method while still being able to leverage the existing `Model.fromJSON` method. Alternatively, if `Model.fromJSON` just called `Model._fromJSON` then I could implement my own `Model.fromJSON` and still call `Model._fromJSON` at the appropriate time. Likewise, in my case, I also need the hook on `Model.prototype.refresh` to alter the data object that is coming back to match my model. I feel like there is a hook that is missing that would simplify things.

Thoughts? Questions? Feedback? Concerns?