voluptuous
バリデーションライブラリ
voluptuous
概要
voluptuousは、Pythonのデータバリデーションライブラリです。主にJSON、YAMLなどの外部から入力されるデータの検証を目的として設計されており、シンプルで読みやすい構文と詳細なエラーメッセージが特徴です。複雑なデータ構造の検証をサポートし、Pythonの基本的なデータ型を使用してスキーマを定義できます。
詳細
voluptuousは、以下の設計原則に基づいて開発されています:
主要な特徴
- シンプルな構文: Pythonの基本的なデータ型(dict、list、int、strなど)を使用してスキーマを定義
- 詳細なエラーメッセージ: 検証エラーが発生した場合、何が問題かを明確に示す有用なメッセージを提供
- ネストされた構造のサポート: 複雑なデータ構造も他のデータ型と同様に扱える
- カスタムバリデータ: 独自の検証ロジックを簡単に追加可能
- 型強制: データを期待する型に自動変換する機能
- オプショナルフィールド: 必須フィールドとオプショナルフィールドの柔軟な定義
設計哲学
- バリデータはシンプルな呼び出し可能オブジェクト: サブクラス化は不要、単純な関数で実装可能
- エラーはシンプルな例外:
Invalid(msg)を投げるだけで有用なメッセージを提供 - スキーマは基本的なPythonデータ構造:
{int: str}のような直感的な記法をサポート - フォーム以外の検証にも対応: APIデータ、設定ファイル、YAMLなど幅広い用途に使用可能
主な用途
- 設定ファイルの検証
- API入力データの検証
- YAML/JSONファイルのバリデーション
- フォームデータの検証
- 環境変数の検証
メリット・デメリット
メリット
- 学習コストが低い: Pythonの基本的なデータ型を使用するため、直感的に理解しやすい
- 依存関係なし: 外部ライブラリに依存しない軽量な実装
- 柔軟性が高い: カスタムバリデータやルールを簡単に追加できる
- エラーメッセージが分かりやすい: デバッグが容易
- コードの可読性: スキーマ定義が読みやすく、ドキュメントとしても機能
- Python的な記法: Pythonic なAPIデザイン
デメリット
- パフォーマンス: Pydanticなどと比較すると処理速度が劣る
- 型アノテーション非対応: Python 3.6+の型ヒントを活用できない
- オブジェクト変換なし: バリデーション後もdictのまま(Pydanticのようなモデルオブジェクトは生成されない)
- IDEサポートが限定的: 型推論やオートコンプリートが効きにくい
- メンテナンス頻度: 他の主要なバリデーションライブラリと比較して更新頻度が低い
参考ページ
書き方の例
基本的な使い方
from voluptuous import Schema, Required
# 基本的なスキーマの定義
schema = Schema({
Required('name'): str,
Required('age'): int,
'email': str # オプショナルフィールド
})
# データの検証
data = {
'name': '山田太郎',
'age': 30,
'email': '[email protected]'
}
validated_data = schema(data)
print(validated_data)
型とバリデーション
from voluptuous import Schema, All, Length, Range
# 制約付きスキーマ
schema = Schema({
Required('username'): All(str, Length(min=3, max=20)),
Required('age'): All(int, Range(min=0, max=150)),
Required('score'): All(float, Range(min=0.0, max=100.0))
})
# 正常なデータ
data = {
'username': 'user123',
'age': 25,
'score': 85.5
}
validated = schema(data)
ネストされた構造
from voluptuous import Schema, Required
# ネストされたスキーマ
address_schema = Schema({
Required('street'): str,
Required('city'): str,
Required('zipcode'): str
})
person_schema = Schema({
Required('name'): str,
Required('addresses'): [address_schema] # アドレスのリスト
})
# 検証
data = {
'name': '田中花子',
'addresses': [
{
'street': '東京都渋谷区1-1-1',
'city': '東京',
'zipcode': '150-0001'
}
]
}
validated = person_schema(data)
カスタムバリデータ
from voluptuous import Schema, Invalid
from datetime import datetime
# カスタムバリデータ関数
def valid_date(date_string):
try:
date = datetime.strptime(date_string, '%Y-%m-%d')
if date > datetime.now():
raise Invalid('日付は未来の日付にできません')
return date_string
except ValueError:
raise Invalid('日付形式が正しくありません (YYYY-MM-DD)')
# カスタムバリデータを使用
schema = Schema({
Required('name'): str,
Required('birth_date'): valid_date
})
data = {'name': '鈴木一郎', 'birth_date': '1990-05-15'}
validated = schema(data)
エラーハンドリング
from voluptuous import Schema, Required, Invalid, MultipleInvalid
schema = Schema({
Required('name'): str,
Required('age'): int,
Required('email'): str
})
# エラーが発生するデータ
invalid_data = {
'name': 123, # 型が違う
'age': 'thirty', # 型が違う
# emailが欠けている
}
try:
validated = schema(invalid_data)
except MultipleInvalid as e:
print("検証エラー:")
for error in e.errors:
print(f"- {error.path}: {error.message}")
高度な使用例 - API入力検証
from voluptuous import Schema, Required, Optional, All, Length, Email, In
# APIエンドポイント用のスキーマ
user_registration_schema = Schema({
Required('username'): All(str, Length(min=3, max=30)),
Required('password'): All(str, Length(min=8)),
Required('email'): Email(),
Required('user_type'): In(['customer', 'vendor', 'admin']),
Optional('phone'): All(str, Length(min=10, max=15)),
Optional('preferences'): {
'newsletter': bool,
'notifications': bool,
'language': In(['ja', 'en', 'zh'])
}
})
# 使用例
def register_user(request_data):
try:
# データ検証
validated_data = user_registration_schema(request_data)
# ここでユーザー登録処理を実行
return {'status': 'success', 'data': validated_data}
except MultipleInvalid as e:
return {
'status': 'error',
'errors': [{'field': str(err.path[0]), 'message': err.msg}
for err in e.errors]
}