JavaScript
reactjs

JSON Schemaとreact-jsonschema-form

More than 1 year has passed since last update.

社内勉強会用資料。社内ツールで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ももっと紹介したい機能があるので、またノウハウを貯めて書きたい