【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を指定して連想配列にすることが非常に重要です。この指定がないとオブジェクトが返され、後続のキー存在チェックが正しく機能しません。また、この検証関数はネストしたオブジェクトや、あってもなくてもよいオプションのキーには対応していません。スキーマに定義されていない余分なキーが含まれていても検証を通過するため、より厳密な仕様が求められる場合は、コードの追加修正や専用ライブラリの利用を検討する必要があります。

関連コンテンツ