エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

【試行】Joiを触ってみる

きっかけ

Top 5 Validation Libraries for JavaScript in 2024 - DEV Community

上記サイトを見て、気になったから。

あと、日本語発音の"ジョイ"で俺が知ってる"ジョイ"といえば、地球圏最強の洗剤"JOY"。
きっと、validator界でも最強のはずという妄想もある。

試そうと思った理由の8割は、JOY
日常生活+ガンプラ作成で使ってるから。
残り2割は、フロントのバリデーション系に触ってみたかったから

公式サイト

自分が使ったバージョンのAPIドキュメントへのリンク

joi.dev - 17.13.3 API Reference

実装

見せてもらおうか、joiのvalidator機能の性能とやらを

環境準備

適当にフォルダを掘ってnpmプロジェクトを作って、joiをインストールする。

$ npm init -y
$ npm i joi

本実装

初めて触るのなら、やっぱり、公式サイトのサンプルを動かすのが一番手っ取り早い。
自分は、index.jsを作ってそこにコピペ。
検証している箇所が微妙に間違えているので、そこだけ手直し。

const Joi = require('joi');

const schema = Joi.object({
    username: Joi.string()
        .alphanum()
        .min(3)
        .max(30)
        .required(),

    password: Joi.string()
        .pattern(new RegExp('^[a-zA-Z0-9]{3,30}$')),

    repeat_password: Joi.ref('password'),

    access_token: [
        Joi.string(),
        Joi.number()
    ],

    birth_year: Joi.number()
        .integer()
        .min(1900)
        .max(2013),

    email: Joi.string()
        .email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } })
})
    .with('username', 'birth_year')
    .xor('password', 'access_token')
    .with('password', 'repeat_password');


console.log("== 正常系 ==")
var result1 = schema.validate({ username: 'abc', birth_year: 1994, password: "123",  repeat_password: "123"});
// -> { value: { username: 'abc', birth_year: 1994, password: '123', repeat_password: '123' } }
console.log(result1)


console.log("== 異常系 ==")
var result2 = schema.validate({ username: 'abc', birth_year: 1994 });
// -> { value: { username: 'abc', birth_year: 1994 } }
console.log(result2);

var result3 = schema.validate({});
// -> { value: {}, error: '"username" is required' }
console.log(result3)

console.log("== Async ==")
try {
  (async function () {
    const value = await schema.validateAsync({ username: 'abc', birth_year: 1994, password: "123",  repeat_password: "123"});
    console.log(value);
  }());
}
catch (err) { }

やっていること

  • ユーザー名
    • 必須文字列
    • 英数字のみ
    • 3文字以上30文字以内
    • birth_yearも設定する( .with('username', 'birth_year')が該当)
  • パスワード
    • オプションの文字列
    • カスタム正規表現パターンを満たす必要がある
    • access_tokenと一緒に指定することはできない(.xor('password', 'access_token')が該当)
    • repeat_passwordと同じでなければなりません( .with('password', 'repeat_password')とrepeat_password: Joi.ref('password'),)
  • access_token
    • 制約のない任意の文字列または数値
  • 誕生年
    • 1900年から2013年までの整数
  • メールアドレス
    • 有効なメールアドレスの文字列
    • 2つのドメインが必要
    • TLDは.comまたは.netでなければなりません

実行結果

自分の端末では、下記のように出てきた。

$ node index.js 
== 正常系 ==
{
  value: {
    username: 'abc',
    birth_year: 1994,
    password: '123',
    repeat_password: '123'
  }
}
== 異常系 ==
{
  value: { username: 'abc', birth_year: 1994 },
  error: [Error [ValidationError]: "value" must contain at least one of [password, access_token]] {
    _original: { username: 'abc', birth_year: 1994 },
    details: [ [Object] ]
  }
}
{
  value: {},
  error: [Error [ValidationError]: "username" is required] {
    _original: {},
    details: [ [Object] ]
  }
}
== Async ==
{
  username: 'abc',
  birth_year: 1994,
  password: '123',
  repeat_password: '123'
}

感想

最近の潮流として、validatorは、チェーンつなぐ感じのやつが多い印象。
joiもその流行に乗って作られている。
理解は、比較的しやすかった。
個人的には、withやxorなんかで複合条件が書きやすいところがメリットのように感じた。
あと、JavaScriptといえば非同期実装みたいなところがあるので、非同期の入力チェックが新鮮だった。

xorって言って通じない人がいるような気がしないでもないが、基礎を抑えてる人なら、すぐに理解できるはず。

今回はJavaScriptで試したけど、TypeScriptならもっと有効活用できるのではないかと感じた。