Search code examples
ember.jsember-datadjango-rest-frameworkjson-api

Dasherize properties for JSONAPI


I have this model in my drf backend:

class Product:

    price_range = ...

I am using EmberData with the JSONApi serializer. I have just found out that JSON API requires dasherized properties. So I need to tell drf:

JSON_API_FORMAT_KEYS = 'dasherize'

And the property gets serialized in the JSON as:

price-range

Then, EmberData does its dance, and I get the Ember model property:

import DS from 'ember-data';

export default DS.Model.extend({
    ...
    priceRange: DS.attr('number'),
    ...
});

(the old RESTSerializer was expecting priceRange in the JSON, if I recall properly)

So, we go from price_range -> price-range -> priceRange (which is pretty crazy if you ask me). I found all this by trial and error. For drf the corresponding settings are documented here.

Where is this documented for JSONApi, EmberData and Ember? I would like to make sure I have really understood this, and that this is also the case for relationships. The related drf config setting would be:

JSON_API_FORMAT_RELATION_KEYS = 'dasherize'

Solution

  • In the blog post for the Ember-Data 1.13 release the Ember data team writes:

    JSONSerializer and RESTSerializer have been refactored and streamlined to return JSON API payloads.

    This means that moving forward Ember Data expects dasherized names in line with JSON API. See the JSON API recommendation for dashes in between words of member names:

    Member names SHOULD contain only the characters "a-z" (U+0061 to U+007A), "0-9" (U+0030 to U+0039), and the hyphen minus (U+002D HYPHEN-MINUS, "-") as separator between multiple words.

    And see some of the example JSON on the JSON API home page:

    -"attributes": {
        "first-name": "Dan",
        "last-name": "Gebhardt",
        "twitter": "dgeb"
    },
    

    As far as the models are concerned, the most recent documentation for Ember 2.2.0 states:

    In Ember Data the convention is to camelize attribute names on a model

    And the example model given with mutli-world attribute names is as expected:

    export default DS.Model.extend({
      firstName: DS.attr('string'),
      lastName:  DS.attr('string'),
    
      isPersonOfTheYear: DS.attr('boolean')
    });
    

    While there definitely has been churn in the recommended naming conventions, I expect that at this point most of these changes are behind us. The core team has taken notice. I believe in the move to standardize around JSON API so that inter-operable and re-usable tooling can be built, but unfortunately that move came along with these changes.

    In summary: Use dasherized names in your JSON and camelized names in your models.

    Edit: It seems that while the Ember Data team went with the JSON API recommendation regarding property names in JSON payloads, it is just that - a recommendation. See this discussion on GitHub regarding the dasherized naming convention for JSON API.