JSONファイルを活用してみる


はじめに

初心者の方たちはこれまでにJSONのファイルを読み込んだりする事はあっても、自分でファイルを作成した事がない人も多いのではないでしょうか?
まさに私がその人間でした。

アプリを作っていると必ず親コンポートから子コンポーネントに情報を渡す為に、propsを渡す記述をしていくことになると思います。そこで初めてJSONファイルを活用してみました。

これから作るもの

まずは作ろうと思っている完成版を先に見てみましょう。
今回の目的はJSONファイルの活用なので、デザインのショボさには目を瞑ってください。

映画詳細の参照サイト

例えばこのように映画の情報を表す3枚のカードがあります。中身の情報が違うだけで、カードの構成は全く同じです。そこで1枚だけのカードをコンポーネント化し、それぞれに映画の「名前、制作年、詳細」の3つ情報を持たせます。
子コンポーネントでは、それぞれを {title},{year},{description}などの適当な名前でpropsとして受け取り表示できるようにしておきます。

ではpropsを渡す親コンポーネントを見てみましょう。
最初に私が書いたコードがこちらです。

/CardComponent.tsx
import React from 'react';
import styles from './CardComponent.module.scss';
import CardItem from './CardItem';

const CardComponent: React.VFC = () => {
  return (
    <div className={styles.card_component_wrapper}>
      <div>
        <CardItem
          title="スタンドバイミー"
          year="1986"
          description="1986年制作のアメリカ映画。1950年代末のオレゴン州の小さな町キャッスルロックを舞台に、それぞれ心に傷を持った4人の少年たちが好奇心から、線路づたいに“死体探し”の旅に出るという、ひと夏の冒険を描く。"
        />
      </div>
      <div>
        <CardItem
          title="マスク"
          year="1994"
          description="1994年のアメリカ映画。主演のジム・キャリーとヒロインのキャメロン・ディアスを一躍トップスターに仕立てた作品。地味な男が不思議な緑色の仮面を手に入れたことから、超人的な力を持った怪人・マスクに大変身する物語である。"
        />
      </div>
      <div>
        <CardItem
          title="タイタニック"
          year="1997"
          description="2200人もの乗客と乗員を乗せたまま沈没した大型豪華客船タイタニック号の海難事故をベースに、上流階級の娘と貧しい青年の悲恋を描く感動のスペクタクル。 アカデミー作品賞、監督賞をはじめ11部門を受賞するという快挙を達成した。"
        />
      </div>
    </div>
  );
};

問題点

コードを書いていて初心者ながら不便さを感じておりました。
それは、渡すpropsの詳細が長すぎることです。
今回は渡す情報がたったの3つなのでこのままでも乗り切れますが、もっとpropsの数が多くて渡したい情報がたくさんある場合や、情報の文字数が長すぎる場合は、親コンポーネントの中身がごちゃごちゃして見づらくなります。
基本的な考え方として、常にファイルの中はスッキリと整理しておきたい。
そして親コンポーネントはだたアプリの構造だけを書いているファイルなので、実際に表示したい映画の詳細のデータまで記述したくはありません。そこでファイルを分けることにしました。

JSONファイルの活用

JSONファイルの事をまだ全く分からない方は先にこちらを参考にしてください。

非エンジニアのためのJSON入門

/ItemDescription.json
[
  {
    "title": "スタンドバイミー",
    "year": 1986,
    "description": "1986年制作のアメリカ映画。1950年代末のオレゴン州の小さな町キャッスルロックを舞台に、それぞれ心に傷を持った4人の少年たちが好奇心から、線路づたいに“死体探し”の旅に出るという、ひと夏の冒険を描く。"
  },
  {
    "title": "マスク",
    "year": 1994,
    "description": "1994年のアメリカ映画。主演のジム・キャリーとヒロインのキャメロン・ディアスを一躍トップスターに仕立てた作品。地味な男が不思議な緑色の仮面を手に入れたことから、超人的な力を持った怪人・マスクに大変身する物語である。"
  },
  {
    "title": "タイタニック",
    "year": 1997,
    "description": "2200人もの乗客と乗員を乗せたまま沈没した大型豪華客船タイタニック号の海難事故をベースに、上流階級の娘と貧しい青年の悲恋を描く感動のスペクタクル。 アカデミー作品賞、監督賞をはじめ11部門を受賞するという快挙を達成した。"
  }
]

まずは新たに拡張子.jsonでJSONファイルを作成します。そしてそのファイル内に、このような複数あるオブジェクトを配列の中に入れた書き方をします。
それを親であるCardComponentで読み込みます。

/CardComponent.tsx
import items from './ItemDescription.json';

itemsとして一旦読み込みます。

そしてpropsとして渡す部分で、配列になったオブジェクトのそれぞれのKeyのValueを取得します。

/CardComponent.tsx
return (
    <div className={styles.card_component_wrapper}>
      <div>
        <CardItem
          title={items[0].title}
          year={items[0].year}
          description={items[0].description}
        />
      </div>
      <div>
        <CardItem
          title={items[1].title}
          year={items[1].year}
          description={items[1].description}
        />
      </div>
      <div>
        <CardItem
          title={items[2].title}
          year={items[2].year}
          description={items[2].description}
        />
      </div>
    </div>
  );

これで別ファイルに分けたJSONファイルからデータを取得し表示する事ができました。

しかし毎回配列番号を何度も記述しなければならず、さらにJSONファイル内のデータの中身が変わった場合には、その都度配列番号を全て変更しないといけない事を考えるともう少しマシな書き方があるのではと思い、以下のようにリファクタリングしてみました。

/CardComponent.tsx
import React from 'react';
import styles from './CardComponent.module.scss';
import CardItem from './CardItem';
import items from './ItemDescription.json';

const CardComponent: React.VFC = () => {

  const card1 = items[0];
  const card2 = items[1];
  const card3 = items[2];
  const card4 = items[3];

  return (
    <div className={styles.card_component_wrapper}>
      <div>
        <CardItem
          title={card1.title}
          year={card1.year}
          description={card1.description}
        />
      </div>
      <div>
        <CardItem
          title={card2.title}
          year={card2.year}
          description={card2.description}
        />
      </div>
      <div>
        <CardItem
          title={card3.title}
          year={card3.year}
          description={card3.description}
        />
      </div>
    </div>
  );
};

export default CardComponent;

正直、これに関しては完全に我流なのでもっと綺麗な書き方がありましたらぜひ教えてください。

我流ではありますが、こちらでもきちんと機能しました。もしJSONファイル内のデータに何かしらの変更があった場合でもあらかじめ定義した部分の配列番号を変更すれば済みます。

まとめ

JSONファイルを用いて外部にデータを分けるメリットとして以下のことが挙げられます。

1. アプリの構造とデータを分けて管理できるので全体の見通しが良くなる。
2. データに変更があった場合に変更を加えやすい。保守性が高い

こちらのコードはReactとTypescriptを使ってコードを書いていますが、今回お伝えした件に関しては言語に関係なくJSONファイルを扱うという点においては基本的に同じ考え方だと思いますので、初学者の方は是非参考にしてみてください。