プログラミング

normalizr の使い方

投稿日:2017年7月11日 更新日:

1. はじめに

JavaScript のライブラリである normalizr の使い方を簡単に説明します。

2. normalizr とは?

normalizr とは、「JSONデータを正規化する」 ためのライブラリです。

正規化」というのはデータベース用語なのですが、このライブラリに関しては以下のような意味合いを持つようです。

  1. 何らかの属性を持つデータは、全てマスター化する(そのため、データの階層はなくなる)。
  2. あるデータの中で他のデータを項目として持つ場合は、id によって参照させる。

3. 使い方ともう少し詳しい説明

paularmstrong/normalizr で、例として挙げられているデータ(JSON)を使ってもう少し詳しく説明します。

元となるデータ(JSON)

{
  "id": "123",
  "author": {
    "id": "1",
    "name": "Paul"
  },
  "title": "My awesome blog post",
  "comments": [
    {
      "id": "324",
      "commenter": {
        "id": "2",
        "name": "Nicole"
      }
    }
  ]
}

このデータ全体が1つの記事(article)を表しており、以下の情報を持っています。

  • この記事の id は、123
  • この記事の著者(author)は、id が 1の Paul さん
  • この記事のタイトル(title)は、”My awesome blog post”
  • この記事に対して書き込まれたコメント(comments)は 1件で、そのコメントは以下の情報を持っています。
    • id が324
    • コメントを書いた人(commenter)の id は2
    • コメントを書いた人(commenter)の名前は Nicole さん

この中で、著者(author)とコメントを書いた人(commenter)は、idname を持ったユーザー(user)であると考えられそうです。データベース的に考えると、ユーザー(user)というマスターデータがあり、著者(author)とコメントを書いた人(commenter)を表すには、このマスターデータに登録されているユーザーの id を指定すれば、データとして無駄がありません(重複がありません)。
また、idcommenter という項目を持つコメント(comments)も、記事(article)の中に丸ごと入れておくのではなく、独立したマスターデータとして存在させておいた方が無駄がありません。記事(article)内では、保持するコメントの id だけ指定しておけば関連していることが分かります。

ということで、無駄のない形でデータを持とうと思うと、

  • ユーザーのデータ
  • コメントのデータ
  • 記事のデータ

をそれぞれマスターデータとして独立させ、関連する部分では id だけ持たせておくというのが一番スッキリしています。これが normalizr の正規化です。

実際には、以下のようにこの 3つデータの Schema情報を定義して、データ構造の情報を補うことで正規化を実行することができます(Schema というのは「データの構造」といった意味になります)。

import { normalize, schema } from 'normalizr';

// (1) ユーザーを表すスキーマを定義します
const user = new schema.Entity('users');

// (2) コメントを表すスキーマを定義します
// - コメントの中には `commenter` という項目があり、それは先ほど定義した `user` がセットされます。
const comment = new schema.Entity('comments', {
  commenter: user
});

// (3) 記事を表すスキーマを定義します
// - 記事には `author` という項目があり、それは `user` がセットされます。
// - 記事は `comments` という項目があり、それは先ほど定義した `comment` の配列になっています。
const article = new schema.Entity('articles', { 
  author: user,
  comments: [ comment ]
});

// (4) このJSONデータ全体は、記事を表しているので `article` のスキーマで正規化します。
const normalizedData = normalize(originalData, article);

これにより、正規化されたJSONが生成されます。

正規化されたデータ(JSON)

{
  result: "123",
  entities: {
    "articles": { 
      "123": { 
        id: "123",
        author: "1",
        title: "My awesome blog post",
        comments: [ "324" ]
      }
    },
    "users": {
      "1": { "id": "1", "name": "Paul" },
      "2": { "id": "2", "name": "Nicole" }
    },
    "comments": {
      "324": { id: "324", "commenter": "2" }
    }
  }
}

この変化を図にまとめました。

JSONを正規化したところ

サーバーから取得したデータ(JSON)などは、必ずしも使いやすい形で得られるわけではないので、今回のように正規化することで、その中から欲しい情報をラクに取得することができるようになります。

4. 関連

webpack Bootstrap

Webpack 4 (もしくは 3) で Bootstrap v4.0 を利用するサンプルコード

2018.01.26

webpack 3 を使ったウェブページ開発手順

2017.06.30

📂-プログラミング
-

執筆者:labo


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Web Components

Web Components: 組み込み要素を拡張する方法

目次1. はじめに2. 組み込みHTML要素を拡張する方法3. おわりに4. 参考 1. はじめに Web Components では、HTMLElement を継承してカスタムクラスを定義することも …

web development

Web Development for Beginners を読む:レッスン6と7

目次1. はじめに2. Lesson 6: JavaScript Basics: Making DecisionsA Brief Recap on Booleans(ブール値の簡単な要約)Compar …

web development

Web Development for Beginners を読む:レッスン18, 19, 20

目次1. はじめに2. Part 4: レーザーと衝突検知を追加する(1) 衝突検知のための「オブジェクトの四角形表現を返す関数」を用意する(2) 衝突検知の判定関数を追加する(3) レーザー発射機能 …

React Redux

React + Redux のチュートリアルをやってみた

目次1. はじめに2. Redux について2. Action と Action CreatorActionAction Creators関連ソースコードactions/index.jscontain …

JavaScript でスロットマシーンを作ってみました(3回目)

「JavaScript でスロットマシーンを作ってみる」の3回目です。 今回は ゲームっぽくしてみました。 目次1. スクリーンショット2. デモページ3. 内容4. ソースコード5. 参考情報 1. …