5

I receive a JSON from our API that has the following format

[
  {
    "id": 45,
    "name": "Pasta",
    "_order": 0,
    "is_hidden": null,
    "is_list": false
  },
  {
    "id": 46,
    "name": "Salads",
    "_order": 1,
    "is_hidden": null,
    "is_list": false
  },
  {
    "id": 47,
    "name": "Dessert",
    "_order": 2,
    "is_hidden": null,
    "is_list": false
  }
];

I see that it has invalid format for standard RESTAdapter and I need to put the name of the model first. In my example it should probably be like:

{
  "category":
    [
      {
        "id": 45,
        "name": "Pasta",
        "_order": 0,
        "is_hidden": null,
        "is_list": false
      },
      {
        "id": 46,
        "name": "Salads",
        "_order": 1,
        "is_hidden": null,
        "is_list": false
      },
      {
        "id": 47,
        "name": "Dessert",
        "_order": 2,
        "is_hidden": null,
        "is_list": false
      }
    ]
  }

So how to make it look this way in my adapter? It seems like I should use DS.RESTSerializer, but I can't figure out which method I should override...

Steve H.
  • 6,912
  • 2
  • 30
  • 49
Tikhon Belousko
  • 767
  • 1
  • 9
  • 26

4 Answers4

4

I ran into this issue earlier today. A nice clean way to fix it is to define a normalizePayload method for your ApplicationSerializer. It's made to be overwritten, so you aren't affecting anything else.

E.g.

App.ApplicationSerializer = DS.RESTSerializer.extend({
    normalizePayload: function(type, payload) {
        return { category: payload };
    }
}

If you want to do this on only some of the payloads processed then you just add a conditional inside it.

App.ApplicationSerializer = DS.RESTSerializer.extend({
    normalizePayload: function(type, payload) {
        if (type.toString() === 'App.Category') {
            return { category: payload };
        }
    }
}

For more info on the normalizePayload method see http://emberjs.com/api/data/classes/DS.RESTSerializer.html#method_normalizePayload

Community
  • 1
  • 1
Paolo
  • 410
  • 3
  • 12
  • I'm using extract method, but this solution looks a little cleaner and nicer! Thanks for your answer! – Tikhon Belousko Feb 15 '14 at 16:39
  • 1
    For a generic normalizePayload that supports different types, you can get the typeKey from the type like this: `var normalizedPayload = {}; normalizedPayload[type.typeKey] = payload; return normalizedPayload;` – carpeliam May 26 '14 at 20:42
3

In general, you'll probably want to implement a couple of methods in your serializer if you have to tweak your JSON:

App.ApplicationSerializer = DS.RESTSerializer.extend({
    normalize: function(type, hash, prop) {
        // change your incoming JSON to ember-style here
    },
    serialize: function(record, options) {
        // change your outgoing ember-data record to your server's JSON here
    }
});

EDIT: You may also in your case need to override extractArray as well: http://emberjs.com/api/data/classes/DS.RESTSerializer.html#method_extractArray

Steve H.
  • 6,912
  • 2
  • 30
  • 49
3

Neither normalizePayload nor normalize is working for me. What I am doing is:

// app/serializers/application.js
import DS from 'ember-data';

export default DS.RESTSerializer.extend({
    extractArray: function(store, type, payload) {
        var payloadTemp = {}
        payloadTemp[type.typeKey] = payload;
        return this._super(store, type, payloadTemp);
    },
    extractSingle: function(store, type, payload, id) {
        var payloadTemp = {}
        payloadTemp[type.typeKey] = [payload];
        return this._super(store, type, payloadTemp, id);
    }
});
Lei Cao
  • 457
  • 6
  • 13
1

Just nest the object represented by your JSON string inside a new object which adds the new property needed and then convert back to JSON. Like this:

var yourInitialJSONString; // your JSON from API 
var obj = JSON.parse(yourInitialJSONString);
var newObj = {
    category: obj
};
var finalJSON = JSON.stringify(newObj);

Alternatively, though probably only best for simple case and not as universally useful as working with actual objects, you could simply concatenate to your JSON:

var yourInitialJSONString; // your JSON from API
var finalJSON = '{"category":' + yourInitialJSONString + '}';

These might prove faster for simple use cases as you avoid deserialization and serialization. I just don't like it as much as I would rather work with actual objects represented by the data. If you need to do a more complex transformation it would probably prove to be more understandable in real word terms than doing a bunch of string concatenation/manipulation.

Mike Brant
  • 70,514
  • 10
  • 99
  • 103