LoginSignup
35
38

More than 5 years have passed since last update.

JSON Schemaとreact-jsonschema-form

Posted at

社内勉強会用資料。社内ツールでJSON Schemaとreact-jsonschema-formを利用しているので、それについての紹介です。

JSON Schema

JSON Schema

JSONの構造を定義するJSON。

例えば、下記のようなユーザを表すJSONがあるとする。

{
  "id": "00000000-0000-0000-0000-000000000001",
  "name": "Taro YAMADA",
  "age": 30
}
  • idはUUIDで、必須項目
  • nameは英字のみで、必須項目
  • ageは0以上の整数で、任意項目

こういう条件だった場合、JSON Schemaで下記のように定義できる。(あくまで一例だけど)

{
  "title": "ユーザー",
  "type": "object",
  "properties": {
    "id": {
      "title": "ID",
      "type": "string",
      "pattern": "^[0-9a-zA-Z]{8}(-[0-9a-zA-Z]{4}){3}-[0-9a-zA-Z]{12}$"
    },
    "name": {
      "title": "ユーザー名",
      "type": "string",
      "pattern": "^[\\sa-zA-Z]+$"
    },
    "age": {
      "title": "年齢",
      "type": "integer",
      "minimum": 0
    }
  },
  "required": [ "id", "name" ]
}

他にも色々と出来るけど、今回は割愛します。一番最初に貼ったリンクで仕様を読むか、下記のドキュメントが分かりやすかったので、そちらで勉強してください。

Understanding JSON Schema — Understanding JSON Schema 1.0 documentation

react-jsonschema-form

mozilla-services/react-jsonschema-form: A React component for building Web forms from JSONSchema.

react-json-schema-formは、JSON Schemaからフォームを生成してくれるReact Component。

Github Pagesにデモページがあるので、試しに先程のJSON Schemaを入れてみると下記のようなフォームが生成される。

image

使い方

Formコンポーネントに、下記のようなpropsを渡せば、最低限動作する。その他のpropsについては後述する。

  • schema ... JSON Schema
  • formData ... JSON
  • onChange ... 変更された時に呼ばれるハンドラ
  • onSubmit ... Submitボタンを押した時に呼ばれるハンドラ
import React from 'react';
import ReactDOM from 'react-dom';
import Form from 'react-jsonschema-form';

const schema = { ... };
const formData = {};

function handleChange({ formData }) {
  // 入力されたデータ
  console.log(formData);
}

function handleSubmit({ formData }) {
  // 入力されたデータ
  console.log(formData);
}

ReactDOM.render(
  <Form
    schema={schema}
    formData={formData}
    onChange={handleChange}
    onSubmit={handleSubmit}
  />,
  document.getElementById('app')
);

カスタマイズ

react-jsonschema-formは、カスタマイズがしやすいのが魅力だと思う。カスタマイズ方法を軽く紹介する。

uiSchema

propsにuiSchemaを渡すと、UI周りのカスタマイズが可能。

  • フィールド名、placeholderなどの変更
  • デフォルトの<input>要素の変更
  • class属性の変更

などなど、いろいろできる。わかりやすいやつを一部を紹介。

例1)helpTextの追加
<Form
  schema={{ ...さっきのJSON Schema }}
  uiSchema={{
    "name": {
      "ui:help": "半角英字、スペースのみ"
    }
  }}
/>

こうすると、

image

こうなる。

例2)placeholder


<Form
  schema={{ ...さっきのJSON Schema }}
  uiSchema={{
    "name": {
      "ui:placeholder": "半角英字、スペースのみ"
    }
  }}
/>

こうすると、

image

こうなる。(エラー起きちゃってるけど)

カスタムField

例えば、JSON Schema上は文字列でURLだが、ファイルアップロードするUIを表示したい場合、独自のFiledを表示することができる。

// JSON的にはURLが欲しい
const schema = {
  type: "string",
  format: "uri"
};

// AssetFieldコンポーネントを`asset`という名前で登録する
const customFields = {
  asset: AssetField,
};

// FieldにAssetFieldコンポーネントを使う
const uiSchema = {
  'ui:field': 'asset'
};

// fieldsに渡す
<Form schema={schema} uiSchema={uiSchema} fields={customFields} />

AssetFieldでは、下記のようにpropsで渡ってくるonChangeに値を渡して上げればOK。

import React, { Component, PropTypes } from 'react';
import uploadFile from './uploadFile';

class AssetField extends Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    // ファイルをサーバにアップロードして
    // URLを取得するような関数
    uploadFile(e.target.files[0]).then(url => {
      // onChangeで上げる値は、
      // JSON Schema通りの値じゃないと
      // validationでエラーになってしまう
      this.props.onChange(url);
    });
  }

  render() {
    const { required, disabled } = this.props;

    // ファイルアップロードを表示
    return (
      <input
        type="file"
        className="form-control"
        required={required}
        disabled={disabled}
        onChange={this.handleChange}
      />
    );
  }
}

export default AssetField;

おわり

とりあえず、こういうのあるよという紹介。JSON Schemaもreact-jsonschema-formももっと紹介したい機能があるので、またノウハウを貯めて書きたい

35
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
38