规范化JSON API标准v1

时间:2015-11-04 01:28:18

标签: json api flux redux

我一直在调查normalizr以展平standard JSON API format中格式化的JSON API数据。有谁能指出我这样做的一些例子?我特别想知道如何处理资源对象关系的normalizr模式(由JSON API标准定义)。在JSON API标准中,有一个"关系"在资源对象中定义的属性,然后是每组相关对象的属性。以下是JSON API格式中包含两个相关产品的单个产品类别的示例:

{
  "jsonapi": {
    "version": "1.0"
  },
  "meta": {
    "time": "0.006"
  },
  "data": [
    {
      "type": "category",
      "id": "6",
      "attributes": {
        "name": "Odwalla"
      },
      "meta": {
        "product_count": "0"
      },
      "relationships": {
        "product": {
          "data": [
            {
              "type": "product",
              "id": "4785"
            },
            {
              "type": "product",
              "id": "4786"
            }
          ]
        }
      }
    }
  ],
  "included": [
    {
      "type": "product",
      "id": "4786",
      "attributes": {
        "name": "Strawberry & Banana Odwalla",
        "description": null,
        "price": "3.19",
        "upc": ""
      }
    },
    {
      "type": "product",
      "id": "4785",
      "attributes": {
        "name": "Blueberry Odwalla",
        "description": null,
        "price": "3.19",
        "upc": ""
      }
    }
  ]
}

该类别中包含的产品列在data.relationships.product.data下,并且这些产品对象包含在包含的数组中。我相信有很多方法可以规范这个;什么是最有效和友好的方式来平整这个Flux / Redux商店?

1 个答案:

答案 0 :(得分:8)

据我所知,json:api提供了规范化数据。相关数据不直接与主要资源嵌套,而是included - 请参阅此Compound DocumentsFetching Includes。 normalizr不适用于这种数据结构,但是如果这是你的意图,你可以轻松地构建一些可以给你与normalizr相同结果的东西。由于json:api是一个非常严格的标准,因此非常适合使用。多数民众赞成就是我试图实现这一目标的方法,其中有许多来自normalizr库的“灵感”......

import { reduce, append } from 'ramda'

export default function normalize({data, included}) {
  let bag = {}
  const result = visit(data, bag)
  visit(included, bag)

  return {
    entities: bag,
    result
  }
}

function visitIterable(obj, bag) {
  return reduce((acc, item) => {
    const entityId = visitEntity(item, bag)
    return append(entityId, acc)
  }, [], obj)
}

function visitEntity(obj, bag) {
  const entityKey = obj.type
  const entityId = obj.id

  if (!bag.hasOwnProperty(entityKey)) {
    bag[entityKey] = {}
  }

  bag[entityKey][entityId] = obj
  return entityId
}

function visit(obj, bag) {
  if (Array.isArray(obj)) {
    return {
      list: visitIterable(obj, bag)
    }
  } else if (typeof obj === 'object') {
    return {
      item: visitEntity(obj, bag)
    }
  }
}