【问题标题】:Redux normalizr - nested API responsesRedux normalizr - 嵌套 API 响应
【发布时间】:2016-11-03 23:20:50
【问题描述】:

如何使用normalizr 处理嵌套的标准化JSON API 响应,这些响应是通过{ data: ... } 标准的关键?

例如Book

{
    data: {
        title: 'Lord of the Rings',
        pages: 9250,
        publisher: {
            data:  {
                name: 'HarperCollins LLC',
                address: 'Big building next to the river',
                city: 'Amsterdam'
            },
        },
        author: {
            data: {
                name: 'J.R.R Tolkien',
                country: 'UK',
                age: 124,
            }
        }
    }
}   

我将如何设计模式来处理嵌套数据键?

【问题讨论】:

  • 您发布的json不遵循JSONAPI specifications。很快,您不能在主资源中嵌套其他资源,但要在有效负载中包含其他资源,您必须使用特定键 include。在主资源中,您只能发送a limited set of informationrelationships 键下的其他资源之间的关系。
  • 你的权利,我会更新问题

标签: javascript reactjs redux normalizr reselect


【解决方案1】:

对于响应中的每个实体,您应该创建自己的架构。

在您的示例中,我们有三个实体 - booksauthorspublishers

// schemas.js
import { Schema } from 'normalizr';

const bookSchema = new Schema('book');
const publisherSchema = new Schema('publisher');
const authorSchema = new Schema('author');

如果某个实体包含需要规范化的嵌套数据,我们需要使用其架构的define 方法。该方法接受具有嵌套规则的对象。

如果我们需要规范化publisherauthor book 实体的props,我们应该将一个对象传递给define 函数,其结构与我们的响应相同:

// schemas.js
bookSchema.define({
  data: {
    publisher: publisherSchema,
    author: authorSchema
  }
});

现在我们可以标准化我们的响应:

import { normalize } from 'normalizr';
import { bookSchema } from './schemas.js';

const response = {
    data: {
        title: 'Lord of the Rings',
        pages: 9250,
        publisher: {
            data:  {
                name: 'HarperCollins LLC',
                address: 'Big building next to the river',
                city: 'Amsterdam'
            },
        },
        author: {
            data: {
                name: 'J.R.R Tolkien',
                country: 'UK',
                age: 124,
            }
        }
    }
}

const data = normalize(response, bookSchema);

【讨论】:

  • 好的,如果你能详细说明的话。听起来很棒。希望为社区的其他人提供一个解释清楚的答案。
  • @AndrewMcLagan 没问题 :) 更新答案。
  • 如果(如上)根响应对象 book 在这种情况下也嵌套在 { data } 中?
【解决方案2】:

我相信您所追求的是assignEntity 函数的使用,该函数可以在normalize 的选项中传递。在这种情况下,它可以让我们在适当的时候过滤掉多余的data 属性并直接找到下面的值。

assignEntity 让您有效地控制数据的每个键的标准化方式。看看here,了解更多关于它的工作原理。

我把这个放在一起做示范,看看:http://requirebin.com/?gist=b7d89679202a202d72c7eee24f5408b6。这是一个sn-p:

book.define({
  data: {
    publisher: publisher,
    author: author,
    characters: normalizr.arrayOf(character)
  }}
);

publisher.define({
  data: {
    country: country
  }
});

const result = normalizr.normalize(response, book, { assignEntity: function (output, key, value, input) {
  if (key === 'data') {
    Object.keys(value).forEach(function(d){
      output[d] = value[d];
    })
  } else {
    output[key] = value;
  }
}});

还请特别参见 Ln 29,其中 characters 的数组包含一些对象,其中一些对象的信息嵌套在 data 中,而另一些则没有。所有都正确归一化。

我还添加了一些部分来展示它如何处理数组和深度嵌套的数据,请参阅 publisher 中的 country 模型。

使用提供的数据,由于缺少 id,您将需要一个 slug,每个架构也包含在示例中。

Normalizr 太棒了,我希望这有助于解释更多关于它的信息 :)

【讨论】:

  • 很好的答案,很棒的例子!
  • 谢谢!如果您认为任何部分都可以从进一步的解释中受益,请告诉我:)
  • 我将使用正确的 JSON-API 响应更新问题
  • 是的,我非常努力地为所有嵌套字符、发布者等获取未定义的子键...我对您的示例所做的唯一更改是我实际上有一个 { id } 键我的实体...见:requirebin.com/?gist=db7d88f9866ff59aad62e01e6b6d630b
  • 因为您的 id 属性嵌套在 data 对象中,您需要告诉 normalizr 专门签入以找到它。看看这个:requirebin.com/?gist=26b016c32f130c8b23024ef045e9d221 :)
猜你喜欢
  • 2016-11-03
  • 2016-05-07
  • 2018-01-29
  • 2021-08-11
  • 1970-01-01
  • 2016-06-10
  • 2017-03-19
  • 2019-03-24
  • 2020-11-29
相关资源
最近更新 更多