[PHP]json_validate関数の使い方と実践例 – JSONバリデーションが簡単に!

PHP

はじめに

PHP 8.3で新しく追加されたjson_validate関数は、JSON文字列の妥当性を効率的にチェックできる便利な機能です。従来のjson_decodeを使った方法と比べて、メモリ効率が良く、パフォーマンスに優れているのが特徴です。

この記事では、json_validate関数の基本的な使い方から実践的な活用例まで、詳しく解説していきます。

json_validate関数とは?

json_validate関数は、与えられた文字列が有効なJSON形式かどうかを判定する関数です。PHP 8.3.0から利用できるようになりました。

基本構文

json_validate(string $json, int $depth = 512, int $flags = 0): bool

パラメータ

  • $json: 検証したいJSON文字列
  • $depth: 最大ネスト深度(デフォルト: 512)
  • $flags: フラグオプション(デフォルト: 0)

戻り値

  • true: 有効なJSON形式の場合
  • false: 無効なJSON形式の場合

基本的な使い方

有効なJSONの検証

<?php
// 有効なJSONの例
$validJson = '{"name": "太郎", "age": 30, "city": "東京"}';

if (json_validate($validJson)) {
    echo "有効なJSONです";
} else {
    echo "無効なJSONです";
}
// 出力: 有効なJSONです
?>

無効なJSONの検証

<?php
// 無効なJSONの例(クォートが不正)
$invalidJson = "{name: '太郎', age: 30}";

if (json_validate($invalidJson)) {
    echo "有効なJSONです";
} else {
    echo "無効なJSONです";
}
// 出力: 無効なJSONです
?>

従来の方法との比較

json_decode を使った従来の方法

<?php
function isValidJsonOld($json) {
    json_decode($json);
    return json_last_error() === JSON_ERROR_NONE;
}

$json = '{"large_data": "' . str_repeat('x', 1000000) . '"}';

// 従来の方法:メモリを大量消費
$isValid1 = isValidJsonOld($json);

// 新しい方法:メモリ効率が良い
$isValid2 = json_validate($json);
?>

パフォーマンス比較

json_validateの主な利点:

  1. メモリ効率: JSONをパース(解析)せず、妥当性のみチェック
  2. 処理速度: 大きなJSONファイルの検証が高速
  3. シンプル: 一つの関数でバリデーション完了

実践的な活用例

Webフォームでの入力検証

<?php
// フォームから送信されたJSONデータの検証
if ($_POST['json_data']) {
    $jsonData = $_POST['json_data'];
    
    if (json_validate($jsonData)) {
        // 有効なJSONの場合、処理を続行
        $data = json_decode($jsonData, true);
        // データベースへの保存処理など
        echo "データを正常に受信しました";
    } else {
        // 無効なJSONの場合、エラーメッセージを表示
        echo "エラー: 無効なJSON形式です";
    }
}
?>

API開発での活用

<?php
// REST APIでのリクエストボディ検証
$requestBody = file_get_contents('php://input');

// まずJSONの妥当性をチェック
if (!json_validate($requestBody)) {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid JSON format']);
    exit;
}

// 妥当な場合のみデコード処理
$data = json_decode($requestBody, true);

// APIの処理を続行
processApiRequest($data);
?>

ファイル読み込み時の事前チェック

<?php
function processJsonFile($filename) {
    if (!file_exists($filename)) {
        throw new Exception("ファイルが見つかりません");
    }
    
    $jsonContent = file_get_contents($filename);
    
    // ファイル内容の妥当性をチェック
    if (!json_validate($jsonContent)) {
        throw new Exception("無効なJSONファイルです");
    }
    
    // 妥当な場合のみ処理
    return json_decode($jsonContent, true);
}

try {
    $data = processJsonFile('config.json');
    echo "設定ファイルを正常に読み込みました";
} catch (Exception $e) {
    echo "エラー: " . $e->getMessage();
}
?>

詳細オプションの活用

最大深度の設定

<?php
// 深くネストされたJSONの例
$deepJson = '{"level1": {"level2": {"level3": {"level4": "value"}}}}';

// 最大深度を3に制限
if (json_validate($deepJson, 3)) {
    echo "有効です(深度3以内)";
} else {
    echo "無効です(深度制限に引っかかりました)";
}
// 出力: 無効です(深度制限に引っかかりました)
?>

フラグオプションの使用

<?php
// 厳密なJSON検証(重複キーを許可しない場合など)
$jsonWithDuplicateKeys = '{"name": "太郎", "name": "花子"}';

// 通常の検証
$isValid1 = json_validate($jsonWithDuplicateKeys);

// フラグを使った厳密な検証(将来的な拡張用)
$isValid2 = json_validate($jsonWithDuplicateKeys, 512, 0);

echo "通常検証: " . ($isValid1 ? "有効" : "無効") . "\n";
echo "厳密検証: " . ($isValid2 ? "有効" : "無効") . "\n";
?>

エラーハンドリングとベストプラクティス

包括的なバリデーション関数

<?php
function validateJsonSafely($json, $maxLength = 1000000) {
    // 1. 文字列長チェック
    if (strlen($json) > $maxLength) {
        return ['valid' => false, 'error' => 'JSON文字列が長すぎます'];
    }
    
    // 2. 空文字チェック
    if (empty(trim($json))) {
        return ['valid' => false, 'error' => 'JSON文字列が空です'];
    }
    
    // 3. JSON妥当性チェック
    if (!json_validate($json)) {
        return ['valid' => false, 'error' => '無効なJSON形式です'];
    }
    
    return ['valid' => true, 'error' => null];
}

// 使用例
$testJson = '{"name": "田中", "age": 25}';
$result = validateJsonSafely($testJson);

if ($result['valid']) {
    echo "検証成功: JSONは有効です";
    $data = json_decode($testJson, true);
    // 処理続行
} else {
    echo "検証失敗: " . $result['error'];
}
?>

ログ出力との組み合わせ

<?php
function logJsonValidation($json, $source = 'unknown') {
    $isValid = json_validate($json);
    
    $logMessage = sprintf(
        "[%s] JSON Validation - Source: %s, Valid: %s, Length: %d",
        date('Y-m-d H:i:s'),
        $source,
        $isValid ? 'YES' : 'NO',
        strlen($json)
    );
    
    error_log($logMessage);
    
    return $isValid;
}

// 使用例
$apiJson = $_POST['data'] ?? '';
if (logJsonValidation($apiJson, 'API_REQUEST')) {
    // 有効なJSONの処理
} else {
    // エラー処理
}
?>

まとめ

json_validate関数は、PHP 8.3の新機能として、JSONバリデーションを効率的に行える優れたツールです。従来のjson_decodeを使った方法と比べて、以下の利点があります:

  • メモリ効率: 大きなJSONでもメモリ消費を抑制
  • 処理速度: 高速なバリデーション処理
  • シンプルさ: 直感的で使いやすいAPI

Web開発でJSONを扱う場面では、まずjson_validateで妥当性をチェックしてからjson_decodeで処理するという流れが推奨されます。これにより、より安全で効率的なアプリケーションを構築できるでしょう。

PHP 8.3以降を使用している場合は、ぜひこの新機能を活用してみてください!

タイトルとURLをコピーしました