【PHP8.x】json_validate関数の使い方
json_validate関数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
json_validate関数は、与えられた文字列が有効なJSON形式であるかどうかを検証する関数です。この関数は、JSON文字列を解析し、エラーが発生しなければtrueを、エラーが発生すればfalseを返します。JSON (JavaScript Object Notation) は、データを構造化して表現するための軽量な形式であり、主にウェブアプリケーションやAPIにおいてデータの交換に用いられます。json_validate関数を使用することで、受信したデータや生成されたデータが正しいJSON形式であるかを事前に確認し、エラーを未然に防ぐことができます。
この関数は、PHP 8.3で導入され、それ以前のバージョンでは利用できません。JSONデータの検証は、データの整合性を保つ上で非常に重要です。例えば、APIから受信したデータが期待される形式と異なると、アプリケーションの動作に予期せぬ影響を及ぼす可能性があります。json_validate関数を使用することで、このような問題を早期に検出し、適切なエラー処理を行うことができます。
具体的には、json_validate関数は、入力された文字列をJSONとして解釈できるかどうかを判断します。解釈可能であればtrueを返し、構文エラーやその他の理由で解釈できない場合はfalseを返します。この関数は、JSONデータのデコード処理を行う前に、データの有効性を確認するために使用されることが一般的です。デコード処理 (json_decode関数など) は、無効なJSONデータに対して実行するとエラーが発生する可能性があるため、事前にjson_validate関数で検証することで、より安定したアプリケーションを開発できます。
構文(syntax)
1json_validate(string $json, int $depth = 512, int $flags = 0): bool
引数(parameters)
string $json, int $depth = 512, int $flags = 0
- string $json: 検証するJSON文字列
- int $depth = 512: 再帰の深さの上限
- int $flags = 0: オプションフラグ
戻り値(return)
bool
JSON文字列が有効なJSON形式である場合にtrueを、そうでない場合にfalseを返します。
サンプルコード
PHP 8.4 json_validate を使ったJSONスキーマ検証
1<?php 2 3/** 4 * JSON文字列の構文と、簡易的なスキーマ(必須キーの存在)を検証します。 5 * 6 * この関数は、まず `json_validate()` を用いてJSON文字列の構文が 7 * 正しい(well-formed)かを高速にチェックします。 8 * その後、指定された必須キーがJSONオブジェクトにすべて存在するかを 9 * 検証することで、簡易的なスキーマチェックを行います。 10 * 11 * より複雑な型チェックやパターン検証など、本格的なJSON Schema仕様に 12 * 基づく検証が必要な場合は、専用のライブラリの使用を検討してください。 13 * 14 * @param string $json 検証対象のJSON文字列。 15 * @param array $schema 検証する必須キーのリスト。例: ['id', 'name'] 16 * @return bool JSONが構文的に正しく、かつスキーマを満たす場合は true、それ以外は false。 17 */ 18function validateJsonAndSchema(string $json, array $schema): bool 19{ 20 // 手順1: `json_validate()` でJSONの構文が正しいかをチェックします。 21 // これにより、不正な形式のJSONを効率的に弾くことができます。 22 if (!json_validate($json)) { 23 return false; 24 } 25 26 // 手順2: 構文が正しいことを確認後、JSONをPHPの連想配列にデコードします。 27 // エラー時に例外をスローするフラグを指定しています。 28 try { 29 $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR); 30 } catch (JsonException $e) { 31 // json_validate()を通過していれば通常ここには到達しません。 32 return false; 33 } 34 35 // 手順3: 簡易的なスキーマ検証として、必須キーがすべて存在するかをチェックします。 36 foreach ($schema as $requiredKey) { 37 if (!array_key_exists($requiredKey, $data)) { 38 // 必須キーが一つでも欠けていれば検証失敗とします。 39 return false; 40 } 41 } 42 43 // すべての検証を通過した場合のみ true を返します。 44 return true; 45} 46 47// --- 以下、サンプルコードの実行例 --- 48 49// 検証に用いるスキーマ(ユーザー情報として 'id' と 'name' を必須とする) 50$userSchema = ['id', 'name', 'email']; 51 52// ケース1: 構文も正しく、スキーマも満たすJSON 53$validJson = '{"id": 1, "name": "Taro Yamada", "email": "taro@example.com", "age": 30}'; 54echo "ケース1(正常): " . (validateJsonAndSchema($validJson, $userSchema) ? 'OK' : 'NG') . PHP_EOL; 55 56// ケース2: 構文は正しいが、スキーマを満たさないJSON('email' キーが欠落) 57$missingKeyJson = '{"id": 2, "name": "Jiro Suzuki"}'; 58echo "ケース2(スキーマ不適合): " . (validateJsonAndSchema($missingKeyJson, $userSchema) ? 'OK' : 'NG') . PHP_EOL; 59 60// ケース3: 構文が不正なJSON(末尾に余分なカンマ) 61$invalidSyntaxJson = '{"id": 3, "name": "Saburo Tanaka", "email": "saburo@example.com",}'; 62echo "ケース3(構文エラー): " . (validateJsonAndSchema($invalidSyntaxJson, $userSchema) ? 'OK' : 'NG') . PHP_EOL; 63 64?>
このサンプルコードは、PHPのjson_validate関数を使用して、JSON文字列の妥当性を検証する方法を示しています。json_validateは、第一引数で受け取った文字列がJSONとして正しい構文であるかをチェックし、結果をbool値(真偽値)で返します。正しい場合はtrue、不正な場合はfalseとなります。この関数は、実際にJSONをデコードしてPHPのデータに変換するjson_decodeよりも高速に動作するため、構文チェックのみを目的とする場合に効率的です。
コード内のvalidateJsonAndSchema関数は、二段階の検証を行います。まず、引数$jsonで受け取った文字列をjson_validateで検証し、構文が不正であれば即座にfalseを返します。構文が正しい場合、次にjson_decodeでPHPの連想配列に変換します。その後、第二引数$schemaで指定された必須キーのリストを元に、変換後のデータに必要なキーがすべて存在するかをarray_key_existsで一つずつ確認します。構文が正しく、かつ必須キーがすべて揃っている場合にのみ、この関数は最終的にtrueを返します。これにより、JSONデータの形式と構造の両方を簡易的に検証できます。
json_validate()関数はJSONの構文、つまり文法が正しいかだけを高速にチェックします。この関数だけでは、データの中身(例えば、必須キーの有無や値の型)までは検証できません。サンプルコードの後半で行っているキーの存在チェックは、あくまで簡易的なスキーマ検証です。そのため、キーはあっても値が空だったり、期待と違う型(数値のはずが文字列など)だったりした場合は検出できない点に注意が必要です。また、json_decode()関数の第二引数にtrueを指定して連想配列に変換しないと、その後のキー存在チェックが正しく動作しません。なお、このjson_validate()関数はPHP 8.3以降で利用可能です。
PHPでJSONをスキーマ検証する
1<?php 2 3/** 4 * JSON文字列が、指定されたスキーマ(構造定義)に適合するかを検証します。 5 * 6 * この関数は2段階の検証を行います。 7 * 1. json_validate() を使用して、文字列が構文的に有効なJSONであるかを確認します。 8 * 2. JSONをデコードし、必須キーの存在と各キーの値のデータ型がスキーマ定義と一致するかを確認します。 9 * 10 * @param string $jsonString 検証対象のJSON文字列 11 * @param array $schema 検証ルールを定義したスキーマ配列。例: ['name' => 'string', 'age' => 'integer'] 12 * @return bool JSONがスキーマに適合する場合にtrue、そうでない場合にfalseを返します。 13 */ 14function validateJsonAgainstSchema(string $jsonString, array $schema): bool 15{ 16 // ステップ1: JSONの構文が正しいか検証する (PHP 8.3以降で利用可能) 17 if (!json_validate($jsonString)) { 18 // 構文的に無効なJSON 19 return false; 20 } 21 22 // JSON文字列をPHPの連想配列に変換 23 $data = json_decode($jsonString, true); 24 25 // ステップ2: スキーマに基づいて構造と型を検証する 26 foreach ($schema as $key => $expectedType) { 27 // キーが存在するかチェック 28 if (!array_key_exists($key, $data)) { 29 return false; // 必須キーが不足している 30 } 31 32 // キーに対応する値を取得 33 $value = $data[$key]; 34 35 // 期待されるデータ型と実際のデータ型が一致するかチェック 36 $actualType = gettype($value); 37 $isValidType = match ($expectedType) { 38 'string' => $actualType === 'string', 39 'integer' => $actualType === 'integer', 40 'double' => $actualType === 'double', // float型も含む 41 'boolean' => $actualType === 'boolean', 42 'array' => $actualType === 'array', 43 'object' => $actualType === 'object', 44 'null' => $actualType === 'NULL', 45 default => false, 46 }; 47 48 if (!$isValidType) { 49 return false; // データ型が一致しない 50 } 51 } 52 53 return true; // 全ての検証をパス 54} 55 56// 検証ルールとなるスキーマを定義 57// 'id'は整数、'name'は文字列、'isActive'は真偽値であることを期待 58$userSchema = [ 59 'id' => 'integer', 60 'name' => 'string', 61 'isActive' => 'boolean', 62]; 63 64// --- 検証の実行例 --- 65 66// 1. 成功例: スキーマに完全に適合するJSON 67$validJson = '{"id": 1, "name": "Alice", "isActive": true}'; 68echo "Valid JSON: "; 69var_dump(validateJsonAgainstSchema($validJson, $userSchema)); // bool(true) 70 71// 2. 失敗例: キーが不足しているJSON ('isActive'がない) 72$missingKeyJson = '{"id": 2, "name": "Bob"}'; 73echo "Missing Key JSON: "; 74var_dump(validateJsonAgainstSchema($missingKeyJson, $userSchema)); // bool(false) 75 76// 3. 失敗例: データ型が違うJSON ('id'が文字列になっている) 77$wrongTypeJson = '{"id": "3", "name": "Charlie", "isActive": false}'; 78echo "Wrong Type JSON: "; 79var_dump(validateJsonAgainstSchema($wrongTypeJson, $userSchema)); // bool(false) 80 81// 4. 失敗例: 構文的に無効なJSON (末尾にカンマがある) 82$invalidSyntaxJson = '{"id": 4, "name": "Dave", "isActive": true,}'; 83echo "Invalid Syntax JSON: "; 84var_dump(validateJsonAgainstSchema($invalidSyntaxJson, $userSchema)); // bool(false)
このPHPコードは、あるJSON形式の文字列が、指定されたルール(スキーマ)通りに作られているかを厳密に検証するためのカスタム関数 validateJsonAgainstSchema を定義しています。この検証は2つのステップで行われます。
まず、第一のステップとして、PHP 8.3から利用可能になった json_validate() 関数を使い、渡された文字列がJSONとして正しい構文で書かれているかを高速にチェックします。この関数は、JSON文字列を引数に取り、構文が正しければtrue、不正であればfalseを返します。構文エラーが見つかった時点で、関数は即座にfalseを返して処理を終了します。
構文チェックを通過すると、第二のステップに進みます。ここでは json_decode() を使ってJSON文字列をPHPの連想配列に変換し、より詳細な内容の検証を行います。あらかじめ定義されたスキーマ配列に基づき、必須のキーが存在するか、そして各キーの値がスキーマで指定されたデータ型(例えば「整数」や「文字列」など)と一致するかを一つずつ確認します。全てのキーとデータ型がスキーマの定義と完全に一致した場合にのみ、この関数は最終的にtrue(検証成功)を返します。一つでもルール違反があればfalse(検証失敗)を返します。
このサンプルコードは、JSONの正しさを2段階で検証します。まずjson_validate()で構文をチェックしますが、この便利な関数はPHP 8.3以降でなければ利用できない点に注意してください。次にjson_decode()でデータをPHPの配列に変換しますが、第二引数にtrueを指定して連想配列にすることが非常に重要です。この指定がないとオブジェクトが返され、後続のキー存在チェックが正しく機能しません。また、この検証関数はネストしたオブジェクトや、あってもなくてもよいオプションのキーには対応していません。スキーマに定義されていない余分なキーが含まれていても検証を通過するため、より厳密な仕様が求められる場合は、コードの追加修正や専用ライブラリの利用を検討する必要があります。