Search code examples
ember.jsember-datajson-api

Ember data: simplify post object with serialize and attrs hash with dashed jsonapi attributes


Here is a simplified example. Keep in mind the actual model is 20 fields and some computed properties.

'order' model

shippingFirstName: DS.attr('string'),
shippingLastName: DS.attr('string'),


template (model passed in as newOrder)

<ul class="thing-list">
  <li class="thing first-name">
    <label class="field text" for="shippingFirstName">
      <div class="label">
        <span>First name</span>
      </div>
      {{input 
        id="shippingFirstName" 
        value=newOrder.shippingFirstName 
        placeholder="......."}}
    </label>
  </li>
...


posted data

data: {
  attributes: {
    shipping-first-name: 'sheriff',
    shipping-last-name: 'derek',
  },
  type: 'orders',
}


desired outcome

{
  shipping_to: {
    first_name: 'sheriff',
    last_name: 'derek',
  },
}


serializer for 'order' (what I would expect to work...)

import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({

  serialize(snapshot, options) {
    let json = this._super(...arguments);
    json = json.data.attributes;

    console.log(json); // shows attributes as shipping-first-name

    json.shipping_to = {
      first_name: json.shippingFirstName,
      last_name: json.shippingLastName,
    };

    delete json.shippingFirstName;
    delete json.shippingLastName;

    return json;
  },

});

but the shipping_to properties to not appear in the post and the other values are in dash-case (JSON:API style)

The docs are great: https://guides.emberjs.com/v2.18.0/models/customizing-serializers but the examples are not dashed keys.


When I fool around with the attrs hash, I can get things working - but it seems very arbitrary and/or I don't understand what is happening.

import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({

  serialize(snapshot, options) {
    let json = this._super(...arguments);
    json = json.data.attributes;

    console.log(json);

    json.shipping_to = {
      first_name: json.whatever_thing_not_dashed,
      last_name: json.whateverThingCamel,
    };

    delete json.whatever_thing_not_dashed;
    delete json.whateverThingCamel;

    return json;
  },

  attrs: {
    shippingFirstName: 'whatever_thing_not_dashed',
    shippingLastName: 'whateverThingCamel',
  },

});

What am I missing? (The names on the backend aren't consistent enough to just turn camel to underscore across the board - and they are nested differently)


Solution

  • First of all since your backend don't expect JSONAPI objects you should use another serializer like JSONSerializer

    https://guides.emberjs.com/v2.18.0/models/customizing-serializers/#toc_jsonserializer

    this will remove the key "data" and "type", then you can use the same hook that you are using to transform the attrs in snake case with Ember.String.underscore and add the key that you want

    http://www.emberjs.com.cn/api/classes/Ember.String.html#method_underscore

    you should also create a specific serializer for your model

    ember g serializer <name of your model>

    that way you change only the specific model that you want and not the whole application