TypeScript のソースコードから JSON のバリデーションをするツール
TypeScript のインターフェイスやクラスの定義を使ってJSONのバリデーションをしたいという場合のため、TypedGateというツールを作りました。
このツールでは JSON Schema などのスキーマを別途定義することなく、TypeScriptソースコードそのもので型をバリデーションすることを目的としています。
例えば、以下のようなTypeScriptの定義がある場合、
export type Gender = 'female' | 'male' | 'other';
// ↓ これが ControlComment です
// この場合 JSON の people プロパティを指しています
// @TG:path .people
export interface People {
name: string;
age: number;
gender: Gender;
isProgrammer: boolean;
}
上記のように // @TG:path .people
という "ControlComment" をインターフェイスの直前に書くことで、JSONの該当する場所と比較して、バリデーションをします。この場合、以下のJSONは Valid
となります。
{
"people": {
"name": "Linus Torvalds",
"age": 49,
"gender": "male",
"isProgrammer": true
}
}
動作の仕組みとしては、インターフェイスの定義の直前の ControlComment に // @TG:path .people
と書いてあるため、 JSONの people
というプロパティの
{
"name": "Linus Torvalds",
"age": 49,
"gender": "male",
"isProgrammer": true
}
の部分が interface People
と比較されたのです。
正しくないJSONの場合
下記の画像の左がJSON、右がインターフェイスの定義とすると、JSONには available
の定義がないためこのJSONは Not Valid
であると出力されます。
右記 interface HomeConfig
の ControlComment では左記JSONの .home
というプロパティと比較せよ、と指示しており、TypedGate は JSON の home
プロパティの部分と比較しますが、JSON には .home.contents[].available
プロパティが欠如しているため、この JSON は Not Valid
になるのです。
また、エラーが発生したソースファイルの場所とJSONのパスが表示されます。
上記の例では、HomeContent
の定義の中で HomeContentName
やら LatestSchedumeMeta
や他複数の型を参照していることがわかると思います。TypedGateはこれらの定義を全て辿るため、 ControlComment はルートの部分だけに書けば動きます(この場合はHomeConfig
に書く)。
使い方
このツールはコマンドラインツールとなっており、動作させるには tsconfig.json
へのパス(--tsconfig
)とソースのファイル名(--src
)、JSONのファイルパス(--json
)を引数に指定する必要があります。
-v
を指定すると詳細なデバッグログを出力します。
インストールなしで使う
以下のコマンドを実行すると、npx
の機能によりお手持ちのPCにインストールすることなくオンザフライで動作できます。
npx typedgate --tsconfig ./tsconfig.json --src ./src/index.ts --json ./some-json-file.json
インストールする
もしインストールをしたいなら、
npm install -g typedgate
とすると
typedgate --tsconfig ./tsconfig.json --src ./src/index.ts --json ./some-json-file.json
で実行できます。
Tips
巨大なプロジェクトで使う
--src
には1つのファイルしか指定できませんが、このツールは内部的に TypeScript Compiler API を利用しているため、import
export
などで指定されたファイルもたどることができます。
そのため、例えば複数のファイルにインターフェイス定義がまたがっている場合、
export * from './user';
export * from './product';
export * from './login-history';
// other exports ...
などのように export
をただ記載したファイルへのパスを指定して動作させることで、それぞれのファイルを辿ってバリデーションすることができます。
上のファイルを index.ts
とした場合、--src
に指定するものは index.ts
へのパスだけです。
複数の ControlComment 定義
例えば、以下のようなJSONがあった場合、
{
"login":{
"providers":{
"twitter":{
"url":"https://twitter.com/twogateinc",
"follower":123
},
"facebook":{
"url":"https://www.facebook.com/TwoGate-inc-646638978844172/",
"follower":321
},
"instagram":{
"url":"https://www.instagram.com/twogateinc/",
"follower":987
}
}
}
}
以下のような複数の ControlComment を利用して、interface 定義を複数箇所でバリデーションすることができます。
// @TG:path .login.providers.twitter
// @TG:path .login.providers.facebook
// @TG:path .login.providers.instagram
export interface ProviderItem {
url: string;
follower: number;
}
※本来であれば以下のように定義できれば良いのですが、Mapped型に未対応のため、現在はできません。
export type ProviderName = 'twitter' | 'facebook' | 'instagram'
// @TG:path .login <<-- こう書きたいところですが、動きません
export class SocialMedium {
providers: { [key in ProviderName]: ProviderItem };
}
export interface ProviderItem {
url: string;
follower: number;
}
配列
このようなJSONがあった場合、
[
{
"num": 123,
},
{
"num": 321,
},
{
"num": 987,
},
{
"num": 456,
}
]
以下のように []
を指定することで配列を示すことができます。
// @TG:path .[]
export interface ArrayInterface {
num: number;
}
また、応用として例えば、
{
"array":
[
{
"num": 123,
},
{
"num": 321,
}
]
}
というようなJSONがあった場合、
// @TG:path .array[]
export interface ArrayInterface {
num: number;
}
というように指定できます。この記法は、jq を参考にしています。
API
現在、本プログラムはCLIツールだけで、Validの場合は exit code = 0
、 Not Valid の場合は exit code = 1
で終了するようになっていて、CIなどで利用できるようにPOSIXの流儀に則った挙動をするようになっています。
ただ、CLIツールだと他のプログラムから利用しづらいため、他のnodeプログラムから import
して使えるような API を準備しています。
制限
TypeScript Compiler API を利用していますが、TypeScript Compiler API で利用できるのがあくまで TypeScript の抽象構文木にアクセスすることまでで、実際の型のチェックは TypeScript の言語処理系を通している訳ではありません。
プリミティブな型 (string
,number
,boolean
,null
) とそれのArray型はもちろん、 Union型 ('female' | 'male'
) 、Enum型には対応していますが、 Intersection型、Mapped型など複雑な型には対応していません。
ControlComment を付与できるものは Interface と Class 定義です。
Author And Source
この問題について(TypeScript のソースコードから JSON のバリデーションをするツール), 我々は、より多くの情報をここで見つけました https://qiita.com/torque-wrench/items/674258b27cad8e093775著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .