Normalizr:如何处理数组数组

Normalizr: how to work with an array of arrays

我正在尝试规范化键盘配置。这是其中的一小部分:

keyboard.json

{
  "rows": [
    [
      { "label": "~" },
      { "label": "1" },
      { "label": "2" },
      { "label": "3" },
      { "label": "4" }
    ],
    [
      { "label": "tab", size: 1.5 },
      { "label": "Q" },
      { "label": "W" },
      { "label": "E" },
      { "label": "R" }
    ]
  ]
}

我的目标是创建一个标准化对象,如下所示:

{
  entities: {
    keys: {
      'k~0': { label: '~' },
      'k10': { label: '1' },
      // etc..
    },
    rows: {
      0: ['k~0', 'k10'],
      1: ['ktab0', 'kQ0'],
      // etc..
    }
  },
  result: {
    rows: [0, 1, /* etc */]
  }
}

目前我有这个:

import { normalize, schema } from 'normalizr'

const keySchema = new schema.Entity('keys', {}, {
  idAttribute: (k) => {
    return `k${k.label}${k.location || 0}`
  }
})

let rowI = 0

const rowSchema = new schema.Entity('rows', {
  keys: [ keySchema ]
}, {
  // btw: I know this is not the best way to set an id, but I'll solve that later
  idAttribute: (a, b, i) => rowI++
})

const keyboardSchema = {
  rows: [ rowSchema ]
}

export default normalize(keyboardData, keyboardSchema)

这基本上是"copies" 行从原来的json 到实体,而不是为每个行实体创建一个新键。见截图:

这就是我迷路的地方。我想我需要某种中间步骤,"within" rowSchema,但我不明白怎么做。

感谢任何帮助!

嗯,谢谢 Whosebug,帮我解决这个问题 :)

我需要的是 processStrategy 用于 rowSchema 功能。我第一次使用它。花了一些时间,但现在我明白发生了什么。

对于任何感兴趣的人,详细的分类(自下而上阅读):

// 5: Lastly here's where we define how a key entity looks like
const keySchema = new schema.Entity('keys', {}, {
  idAttribute: (k) => {
    // 6: This time we construct the id from properties found in the json
    return `k${k.label}${k.location || 0}`
  }
})

// 2: Defining an Entity makes it appear in the `entities` object within our normalised data
const rowSchema = new schema.Entity('rows', {
  // 3: Here we do the same as before. We assign `keys` the keySchema...
  //    ..but wait.. `keys` is not defined in our json. We simply have a nested array. See 4
  keys: [ keySchema ]
}, {
  // (EXTRA) Each row we assign an id by checking which row's entry matches the current
  idAttribute: (value, parent) => parent.rows.indexOf(value),
  // 4: THIS is how we tell rowSchema that it should assign the current value to keys
  processStrategy: (value) => ({ keys: value })
})

// 1: This looks like destructuring; `rows` should match rows in the JSON
//    Here we say that rows contains an array and each entry should be given the "layout" of `rowSchema`
const keyboardSchema = {
  rows: [ rowSchema ]
}



// All nice and ESNexty:
import { normalize, schema } from 'normalizr'

const keySchema = new schema.Entity('keys', {}, {
  idAttribute: (k) => `k${k.label}${k.location || 0}`
})

const rowSchema = new schema.Entity('rows', {
  keys: [ keySchema ]
}, {
  idAttribute: (keys, { rows }) => rows.indexOf(keys),
  processStrategy: (keys) => ({ keys })
})

const keyboardSchema = {
  rows: [ rowSchema ]
}

export default normalize(keyboardData, keyboardSchema)