【问题标题】:Unable to use Ember data with JSONAPI and fragments to support nested JSON data无法使用带有 JSONAPI 和片段的 Ember 数据来支持嵌套的 JSON 数据
【发布时间】:2017-10-09 04:58:23
【问题描述】:

概述

我正在使用 Ember 数据并拥有 JSONAPI。一切正常,直到我有了一个更复杂的对象(比如说一个通用概念的发票),其中包含一个名为 lineEntries 的项目数组。行条目不直接映射到表,因此需要存储为原始 JSON 对象数据。行输入模型还包含默认值和计算值。我希望将列表数据存储为 JSON 对象,然后在从存储中加载回来时,我可以在 Ember 中将其作为模型的数组正常操作。

我尝试过的

我已经查看并尝试了几种方法,最好的方法似乎是(在这里接受建议!):

片段

用片段替换问题模型

我尝试将行条目模型设为片段,然后将发票模型上的片段作为片段数组引用。行条目正常添加到数组中,但默认值不起作用(应该吗?)。它创建对象,我可以将它存储在后端,但是当我返回它时,它会因规范化问题或序列化程序问题而失败。谁能说明返回数据的格式?这令人困惑,因为规范化数据似乎需要 JSONAPI,但片段需要 JSON 序列化器。我已经尝试了几种组合,但到目前为止没有运气。我的行条目没有实际的 ID,因为数据作为块保存和加载。这是个问题吗?

DS.EmbeddedRecordsMixin

虽然 JSONAPI 不支持,但听起来可以使用 JSONAPI,然后为问题模型切换到 JSONSerializer 或 RESTSerializer。如果可能的话,有人可以给我一个工作示例和 API 应该返回的 JSON 格式吗?我有标头授权和其他此类数据,所以我仍然可以在应用程序级别为所有不使用我的 JSONAPI 的请求进行设置吗?

Ember-data-save-relationships

我在here 上找到了一个插件,它提供了一个插件来执行此操作。它似乎比其他方法更复杂,但是当我尝试这个时,我可以通过将数据设置为嵌入来发送数据。伟大的!但是虽然它保存了它并没有正确解开它,而且我又遇到了同样的问题。

自定义序列化程序

将模型序列化器替换为获取数据并将其作为纯 JSON 数据发送,然后反序列化回 Ember 可以使用的东西。这听起来与上面类似,但我做的是繁重的工作。这样做的唯一原因是因为上述解决方案的所有示例都很简单,并没有真正展示如何使用需要它的实际 JSONAPI 设置来设置它。

我在哪里,我需要什么

基本上所有方法都可以很好地保存 JSON,但从服务器返回的 JSON 格式不正确或反序列化失败,但不清楚它应该是什么或需要更改什么而不破坏现有的正常工作的 JSONAPI 模型。

如果有人知道返回 API 数据的格式,它可能会解决这个问题。我试过 JSONAPI 与 lineEntries 返回相同的格式,因为它保存。我已经尝试放置关系部分,如建议的添加,我还尝试将仅关系数据放在条目和包含所有引用的包含部分。任何关于这方面的帮助都会很棒,因为我通过这个学到了很多东西,但是最后期限迫在眉睫,我看不到一个可行的解决方案,它不会像它修复的那样破坏。

【问题讨论】:

    标签: serialization ember.js ember-data json-api


    【解决方案1】:

    如果您正在寻找来自 API 服务器的关系数据的返回格式,您需要确保以下几点:

    1. 确保在 ember 模型中定义了关系
    2. 返回所有成功,状态码为 200

    从那里您需要确保正确返回关系数据。如果您已将关系的 ember 模型设置为 {async: true},您只需返回关系模型的 id - 它也应该在 ember.xml 中定义。如果您不设置{async: true},则ember 期望包含所有关系数据。

    1. 返回具有 JSON API 规范中关系的数据

    示例:

    models\unicorn.js 在余烬中:

    import DS from 'ember-data';
    
    export default DS.Model.extend({
      user: DS.belongsTo('user', {async: true}),
      staticrace: DS.belongsTo('staticrace',{async: true}),
      unicornName: DS.attr('string'),
      unicornLevel: DS.attr('number'),
      experience: DS.attr('number'),
      hatchesAt: DS.attr('number'),
      isHatched: DS.attr('boolean'),
      raceEndsAt: DS.attr('number'),
      isRacing: DS.attr('boolean'),
    });
    

    GET/:id上的api服务器上的routes\unicorns.js

    var jsonObject = {
      "data": {
        "type": "unicorn",
        "id": unicorn.dataValues.id,
        "attributes": {
          "unicorn-name" : unicorn.dataValues.unicornName,
          "unicorn-level" : unicorn.dataValues.unicornLevel,
          "experience" : unicorn.dataValues.experience,
          "hatches-at" : unicorn.dataValues.hatchesAt,
          "is-hatched" : unicorn.dataValues.isHatched,
          "raceEndsAt" : unicorn.dataValues.raceEndsAt,
          "isRacing" : unicorn.dataValues.isRacing
        },
        "relationships": {
          "staticrace": {
            "data": {"type": "staticrace", "id" : unicorn.dataValues.staticRaceId}
          },
          "user":{
            "data": {"type": "user", "id" : unicorn.dataValues.userId}
          }
        }
      }
    }
    res.status(200).json(jsonObject);
    

    在 ember 中,您可以通过链接模型函数来调用它。例如当这只独角兽去controllers\unicornracer.js比赛时:

    raceUnicorn() {
      if (this.get('unicornId') === '') {return false}
      else {
      return this.store.findRecord('unicorn', this.get('unicornId', { backgroundReload: false})).then(unicorn => {
        return this.store.findRecord('staticrace', this.get('raceId')).then(staticrace => {
          if (unicorn.getProperties('unicornLevel').unicornLevel >= staticrace.getProperties('raceMinimumLevel').raceMinimumLevel) {
            unicorn.set('isRacing', true);
            unicorn.set('staticrace', staticrace);
            unicorn.set('raceEndsAt', Math.floor(Date.now()/1000) + staticrace.get('duration'))
            this.set('unicornId', '');
            return unicorn.save();
          }
          else {return false;}
        });
      });
      }
    }
    

    以上代码发送PATCH到api服务器路由unicorns/:id

    关于GET,POST,DELETE,PATCH的最后说明:

    GET 假设您正在获取与模型相关的所有信息(上面的示例显示了GET 响应)。这与 model.findRecord (GET/:id)(需要一条记录)、model.findAll(GET/)(需要一个记录数组)、model.query(GET/?query=&string=)(需要一个数组)相关联记录),model.queryRecord(GET/?query=&string=)(需要一条记录)

    POST 假设您至少将 POST 从 ember 返回到 api 服务器,但也可以返回您在 apiServer 端创建的其他信息,例如 createdAt 日期。如果返回的数据与您用于创建模型的数据不同,它将使用返回的信息更新创建的模型。这与 model.createRecord(POST/)(需要一条记录)相关联。

    DELETE 假设您返回类型和已删除对象的 id,而不是数据或关系。这与 model.deleteRecord(DELETE/:id)(期望一条记录)相关联。

    PATCH 假设您至少返回了更改的信息。如果您只更改一个字段,例如在我的 unicorn 模型中,unicornName,它只会修补以下内容:

    {
      data: {
        "type":"unicorn",
        "id": req.params.id,
        "attributes": {
          "unicorn-name" : "This is a new name!"
        }
      }
    }
    

    所以它只期望至少返回的响应,但是像POST,你可以返回其他更改的项目!

    我希望这能回答您关于 JSON API 适配器的问题。大部分信息最初是通过阅读 http://jsonapi.org/format/ 的规范和 https://emberjs.com/api/data/classes/DS.JSONAPIAdapter.html 的 ember 实现文档获得的

    【讨论】:

    • 首先,感谢您的详细回复。我已经有了标准响应,所以这个问题特定于子模型未映射到资源的关系。看到相同格式的数据很有用,因此我能够专注于其他领域。到目前为止,我发现我可以返回关系,只需键入和 id,然后在数据属性之后“包含”一个包含条目的列表,这些条目实际上并不存在于子模型之外。不理想,但它让我参与其中。你是怎么做到的?您的示例显示了关系,但没有针对它们的数据。
    • 我在答案顶部包含的 {async:true} 意味着一旦 ember 获得这些记录 id,它将查询 API 服务器以获取这些相关记录 - 这意味着我不必包括数据(你似乎正在做的方式)。我重新阅读了您正在尝试做的事情,没有示例代码很难确定失败的位置。
    • 也许我的问题不清楚。这个问题与异步无关。这是模型中的一个属性,子关系作为单个条目存储在后端的非关系数据库中。 Ember 无法对此进行查询,因为它们表示单个列中的元素并且没有 API 入口点。 Ember 中的非 JSONAPI 的嵌入式记录混合解决了这个问题,片段也做了类似的事情。我即将解决此问题,因此如果之前没有人参与,我将更新问题并提供答案!
    • 嗨 Walter,我正在这里解决一些类似的问题 stackoverflow.com/questions/44713406/… 如果您找到/找到了解决方案,请告诉我!
    猜你喜欢
    • 2015-11-30
    • 2016-09-17
    • 2015-03-27
    • 1970-01-01
    • 2021-10-04
    • 2013-04-19
    • 2015-11-15
    • 2012-08-15
    • 2015-10-05
    相关资源
    最近更新 更多