Ember JS - 规范Facebook Graph API

时间:2016-09-01 13:50:13

标签: json facebook-graph-api ember.js ember-data

我正在开发一个Ember应用程序,该应用程序聚合来自Facebook的Graph API和Rails API的内容。由于我编写了Rails API并且可以控制JSON格式,因此我在使用Ember应用程序查询和提供该内容时没有任何问题。但是,我在规范Facebook Graph API内容方面遇到了一些困难。

举个例子,这是Facebook API提供的一些Feed JSON:

{
"data": [
    {
        "id": "604231966385537_765079483634117",
         "type": "link",
         "message": "They're watching you...",
         "from": {
             "name": "Kristian Twombly",
             "id": "10154089935544635"
         }
    },
    {
         "id": "604231966385537_765057943636271",
         "type": "status",
         "message": "The boss's new ride. He saw mine and had to have one.",
         "from": {
            "name": "Walter Johnson",
            "id": "10206908914060788"
         }
    },
    {
     "id": "604231966385537_764751447000254",
     "type": "photo",
     "message": "Found 1 at Target Apple Valley",
     "from": {
        "name": "Quentin Waterkamp",
        "id": "10210042929332132"
     },
     "comments": {
        "data": [
           {
              "created_time": "2016-09-01T01:33:55+0000",
              "from": {
                 "name": "Riley Richardson",
                 "id": "1189835384423610"
              },
              "message": "Are these rare to find or something?",
              "id": "764829800325752"
           },
           {
              "created_time": "2016-09-01T04:33:44+0000",
              "from": {
                 "name": "Quentin Waterkamp",
                 "id": "10210042929332132"
              },
              "message": "seems to be I was also at a Walmart today and didn't see one and the other Target in Apple Valley didn't have any the other day.",
              "id": "764893193652746"
           }
        ],
        "paging": {
           "cursors": {
              "before": "WTI5dGJXVnVkRjlqZAFhKemIzSTZAOelkwT0RJNU9EQXdNekkxTnpVeU9qRTBOekkyT1RNMk16VT0ZD",
              "after": "WTI5dGJXVnVkRjlqZAFhKemIzSTZAOelkwT0Rrek1Ua3pOalV5TnpRMk9qRTBOekkzTURRME1qUT0ZD"
           }
        }
      },
    }
],
"paging": {
      "previous": "https://graph.facebook.com/v2.7/604231966385537/feed?fields=id,type,message,from,comments&icon_size=16&since=1472731871&access_token=1333570303337296|ssnHtq9p3DuFAxX23XRx7Dc1reQ&limit=25&__paging_token=enc_AdBfsb6FAxWTzuRVAHs3OujbQ3O0Ry2z7QIHq40E45FaLZAyf2mYy888ZASAEiw7D0N31xuAij5ZBsYVZBeVPZAXz5HfDAN2ZAklhsRHRjMu7qLzdODgZDZD&__previous=1",
      "next": "https://graph.facebook.com/v2.7/604231966385537/feed?fields=id,type,message,from,comments&icon_size=16&access_token=1333570303337296|ssnHtq9p3DuFAxX23XRx7Dc1reQ&limit=25&until=1472348927&__paging_token=enc_AdBhRIcyqcv8ZByyC5GnCv2PfoIzySxiZCSdRw3LoOCE2gj51ZCMv9l7OPGWLcrJeHal9Tna2rhsGEul5jEzN93dBA1BXhzdgZCmOOT9y8OqDZCSh2wZDZD"
   }
}

鉴于根元素是data,我最初认为它是在JSON API规范中提供的。但是,缺少attributes键意味着默认的Ember JSONAPISerializer在没有一些修改的情况下不起作用。相反,data键的存在意味着JSONSerializer也无法正确解析JSON。

我没有幸运获得JSON为所有对象正确序列化。如果我删除comments上的/app/models/facebook-photo.js属性,我可以填充顶层对象(如照片,链接,状态)(我在Chrome中使用Ember Inspector确认了这一点)。但是,我无法序列化hasMany的嵌入式comments关系。当我尝试运行我的Ember应用程序时,我当前收到以下错误:

  

extractembeddedhasmany无法读取null

的属性'id'

任何人都可以帮助我了解如何从Facebook API正确规范化JSON吗?此外,如何正确配置hasMany的{​​{1}}关系?

作为参考,这是我的最新代码(我只包含了comments的代码以进行简化):

请注意:我已经使用了facebook-photomodelNameFromPayloadKey序列化程序方法,因为我的Facebook API模型在类型名称后附加了“facebook-”(模型名称与我的冲突)其他API的类型)。

/app/routes/index.js

payloadKeyFromModelName

/app/adapters/facebook-feed.js:

import Ember from 'ember';

export default Ember.Route.extend({
    model() {
        return Ember.RSVP.hash({
            facebookFeedObjects: this.get('store').query('facebook-feed', {
                fields: 'id,type,message,from,comments',
                access_token: '1333570303337296%7CssnHtq9p3DuFAxX23XRx7Dc1reQ'
            })
        });
    }
});

/app/models/facebook-photo.js:

import Ember from 'ember';
import DS from 'ember-data';

export default DS.JSONAPIAdapter.extend({
    host: 'https://graph.facebook.com/v2.7',
    namespace: '604231966385537',
    pathForType: function(type) {
        return 'feed';
    }
});

/app/serializers/facebook-feed.js:

import Model from 'ember-data/model';
import attr from 'ember-data/attr';
import { belongsTo, hasMany } from 'ember-data/relationships';

export default Model.extend({
    message: attr(),
    comments: hasMany('facebook-comment', { polymorphic: true })
});

/app/serializers/facebook-photo.js:

import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({
    modelNameFromPayloadKey(key) {
        let withPrefix = 'facebook-' + key;
        return this._super(withPrefix);
    },

    payloadKeyFromModelName(modelName) {
        let type = this._super(modelName);
        return `${type.replace('facebook-', '')}`;
    }
});

/app/templates/index.hbs:

import DS from 'ember-data';

export default DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, {
    modelNameFromPayloadKey(key) {
        let withPrefix = 'facebook-' + key;
        return this._super(withPrefix);
    },

    payloadKeyFromModelName(modelName) {
        let type = this._super(modelName);
        return `${type.replace('facebook-', '')}`;
    },

    attrs: {
        comments: { embedded: 'always' }
    }
});

1 个答案:

答案 0 :(得分:1)

我认为你最好的选择就是写下own custom serializer。类似的东西:

export default DS.JSONAPISerializer.extend({
  serialize(snapshot, options) {
    var json = this._super(...arguments);

    json.data.attributes.message = json.data.message;
    json.data.attributes.from = {
      name: json.data.from.name,
      id: json.data.from.id
    }

    delete json.data.message;
    delete json.data.from

    return json;
  },
});

请注意,这不会考虑评论字段,但您应该可以执行类似的操作来构建关系以遵守JSON API format