Struggling with Normalizing JSON Response


#1

Good day, all you wonderful ember.js people! :slight_smile:

I am trying to consume an API that is returning JSON in a non-standard format. The response looks like thisL

 {
    "Search":[
        {"Title":"something", "Year":2000",...},
        {"Title":"something else", "Year":1995",...},
        {"Title":"another thing", "Year":1985",...},
    ],
    "total results":"221","Response":"True"
}

And of course I’m seeing this error, since there is no ‘type’ key:

Error while processing route: movies Cannot read property 'type' of undefined TypeError: Cannot read property 'type' of undefined

My model is name ‘movie’. I’m trying to figure out how to inject ‘type’:‘movie’ in the response, wrap each item with an ‘attributes’ key, or otherwise do what I need to do to normalize the response, but I’m not quite understanding the docs I’ve been reading. And don’t I also need to add a ‘data’ key at the very beginning of the payload (replace ‘Search’ with ‘Data’)?

Also-- I’m using a JSONAPIAdapter-- should I use a ‘RESTAdapter’ since this is a non-standard format?

Thanks! Bryan


#2

We use the RESTAdapter in our app to do some customization on the responses. Our API actually probably fits the JSONSerializer (not to be confused with the JSONAPISerializer) even better so I’m not sure why we don’t use that… This blog article seems like a decent overview of the differences. It’s probably a little out of date though so don’t use it for anything more than a broad overview. In your case I’d say probably steer clear of JSONAPISerializer and use RESTAdapter or JSONAdapter, but that’s just off the top of my head, definitely do some research.

Unfortunately it can be a little daunting to try and figure out what methods to override to get the data how you want it. The intro text in the API docs (the stuff above the index) is a great overview of the different methods, what they do, and when they are called in the serialization process. If you were using the JSONSerializer for example, the API docs say the following:

You can customize how JSONSerializer processes its payload by passing options in the attrs hash or by subclassing the JSONSerializer and overriding hooks:

  • To customize how a single record is normalized, use the normalize hook.
  • To customize how JSONSerializer normalizes the whole server response, use the normalizeResponse hook.
  • To customize how JSONSerializer normalizes a specific response from the server, use one of the many specific normalizeResponse hooks.
  • To customize how JSONSerializer normalizes your id, attributes or relationships, use the extractId, extractAttributes and extractRelationships hooks.

The JSONSerializer normalization process follows these steps:

  • normalizeResponse - entry method to the serializer.
  • normalizeCreateRecordResponse - a normalizeResponse for a specific operation is called.
  • normalizeSingleResponse | normalizeArrayResponse - for methods like createRecord we expect a single record back, while for methods like findAll we expect multiple methods back.
  • normalize - normalizeArray iterates and calls normalize for each of its records while normalizeSingle calls it once. This is the method you most likely want to subclass.
  • extractId | extractAttributes | extractRelationships - normalize delegates to these methods to turn the record payload into the JSON API format.

For starters, for the above stuff you wrote, you’d probably want to override normalizeArrayResponse to make changes that deal with the whole response, and then override normalize to deal with each individual record.

Anyway, hope that gets you started, there’s a lot there and some of the docs are anemic, but there are some other good resources out there too. And of course you can always ask more specific questions here if you get too deep in the weeds.