16
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

せっかくTypescriptなんだからJSONを自動でvalidationしよう(ajv+typescript-json-schema)

Last updated at Posted at 2019-12-19

はじめに

  • Validationコードを手で書きたくなかった
  • JSON schemaを手書きしたくなかった(typescriptの型定義を使ってほしい)

国内外たくさんやってることだけど、真似しても使うのに時間がかかった。
最小構成のコードを書く。

まず、Validationができてない状態とは?

index.ts
interface Cat { 
    name: string,
    age: number
}

const catObj = JSON.parse('{"name":"tamago", "weight":2.0}');
const cat = catObj as Cat;

console.log(cat.age); //undefined (Catのageはオプショナルじゃないのに!)

さあ、validationしよう

  1. 実行前にtypescriptコードからtypescript-json-schemaでJSON schema(.json)を生成する
  2. 実行時にajvでJSON Schemaを読み込んで、JSONをvalidationする

1.実行前にtypescriptコードからtypescript-json-schemaでJSON schema(.json)を生成する

typescript-json-schemaをインストール

% npm install typescript-json-schema -g

typescriptコードからJSON schemaを生成

型情報が含まれるtypescriptファイル

cat.ts
interface Cat { 
    name: string,
    age: number
}

export {Cat};

cat.tsのCat型のスキーマをCatSchema.jsonに吐き出す
(cat.tsのように単独ファイルにしていなくてもいい)

% typescript-json-schema --strictNullChecks true --noExtraProps true cat.ts Cat > CatSchema.json

--strictNullChecks Make values non-nullable by default. [boolean] [default: false]
--noExtraProps Disable additional properties in objects by default. [boolean] [default: false]

2. 実行時にajvでJSON Schemaを読み込んで、JSONをvalidationする

ajv他をインストール

% npm install ajv --save
% npm install @types/node --save-dev
% npm install @types/ajv --save-dev

コード全体

index.ts
import * as fs from 'fs'
import * as Ajv from 'ajv';

import {Cat} from './cat' 

const myJSON = '{"name":"tamago", "weight":2.0}'
const catObj = JSON.parse(myJSON);

const ajv = new Ajv();
const catSchema = JSON.parse(fs.readFileSync('./CatSchema.json').toString());
const validate = ajv.compile(catSchema);

if(validate(catObj)){
    console.log('validation ok');

    //安心してasを使おう
    const myCat = catObj as Cat;
}
else{
    console.log('validation ng');
    console.error(validate.errors);
}

実行

% ts-node index.ts
validation ng
[ { keyword: 'additionalProperties',
    dataPath: '',
    schemaPath: '#/additionalProperties',
    params: { additionalProperty: 'weight' },
    message: 'should NOT have additional properties' } ]

ts-node便利なのでよく使っています。

typescriptの型定義のオプショナルもちゃんと扱ってくれるようです。

まとめ

事前のJSON Schema生成はいるが、自動でvalidation環境が作れる。
丁寧な日本語メッセージを返したい場合は、ErrorObject型をアレコレしましょう。

Typescriptの標準機能で欲しい。

16
7
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
16
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?