LoginSignup
1
0

zod や valibot で string → boolean

Last updated at Posted at 2023-11-02

やりたいこと

zodvalibot"true", "false" を boolean の true, false に 変換 しつつ validation

valibot ・ zod とは

どちらもランタイム時にvalidationを行うライブラリで、valibotの方が後出です。

スクリーンショット 2023-11-03 1.35.24.png

現時点では、valibotは出て半年も経っていないので、zodが広く使われています。

valibotzod と似たような定義の方法とメソッド名で、スキーマを定義でき軽量なのが特徴です。

zodと比較すると、バンドルサイズは約半分ぐらいなんだそうです。

スクリーンショット 2023-11-03 1.51.03.png

背景

nextjs の server actions を使っていると、schema は boolean だけども、FormDataから送信するときには、string にしないといけない場合がでてきました。
action送信時に、"true", "false" を boolean の true, false に変換が必要になったので zodvalibot で変換してみました。

どちらもschema をちょっと変更するだけで出来ました。

例えば、Todoアプリがあるとして、下記のようなschemaだったとします。

zodの場合

import { z } from 'zod';

const TodoSchema = z.object({
  id: z.string(),
  title: z.string(),
  description: z.string(),
  completed: z.boolean(),
});

valibotの場合

import { boolean, object, string } from 'valibot';

export const TodoSchema = object({
  id: string(),
  title: string(),
  description: string(),
  completed: boolean(),
});

validationするデータ

{
  id: '548a7df1-2dc6-47db-9ad4-2c5c955966d2',
  title: 'ゴミ捨て',
  description: '水曜ねー',
  completed: 'false'  // 文字列で来てしまう
}

FormDataから取得するとbooleanは文字列になっているので、これを変換し、validationします。

string → boolean に parse

zodの場合

zod-parse
import { z } from 'zod';

const TodoSchema = z.object({
  id: z.string(),
  title: z.string(),
  description: z.string(),
- completed: z.boolean(),
+ completed: z.preprocess((input) => JSON.parse(`${input}`), z.boolean()),
});

const validated = TodoSchema.parse({
  id: '548a7df1-2dc6-47db-9ad4-2c5c955966d2',
  title: 'ゴミ捨て',
  description: '水曜ねー',
  completed: 'false'
});
結果
{
  id: '548a7df1-2dc6-47db-9ad4-2c5c955966d2',
  title: 'ゴミ捨て',
  description: '水曜ねー',
  completed: false
}

valibotの場合

valibot-parse
import { boolean, object, string, coerce, parse } from 'valibot';

const TodoSchema = object({
  id: string(),
  title: string(),
  description: string(),
- completed: boolean(),
+ completed: coerce(boolean(), (input) => JSON.parse(`${input}`)),
});

const validated = parse({
  id: '548a7df1-2dc6-47db-9ad4-2c5c955966d2',
  title: 'ゴミ捨て',
  description: '水曜ねー',
  completed: 'false'
});
結果
{
  id: '548a7df1-2dc6-47db-9ad4-2c5c955966d2',
  title: 'ゴミ捨て',
  description: '水曜ねー',
  completed: false
}

ポイント

  • zod: preprocessを使用
  • valibot: coerceを使用
  • JSON.parse を使って、文字列・boolean値のどちらにも対応
JSON.parse("true"); // => true
JSON.parse("false"); // => false

JSON.parse(true); // => true
JSON.parse(false); // => false

これで、大きな変更なく、値の変換 と validation が 両立できました。

1
0
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
1
0