[PHP]json_encode関数完全マスター – 配列・オブジェクトをJSONに変換する方法

PHP

はじめに

Web APIの開発やフロントエンドとの連携において、PHPのデータをJSON形式に変換する場面は非常に多くあります。そんな時に活躍するのが「json_encode」関数です。

この記事では、PHP初心者から上級者まで、json_encode関数の基本的な使い方から高度な活用テクニックまで、実践的な例を交えながら詳しく解説していきます。

json_encode関数とは?

json_encode関数は、PHPの変数(配列、オブジェクト、文字列、数値など)をJSON形式の文字列に変換する関数です。Web APIのレスポンス作成や、JavaScriptとのデータ受け渡しに欠かせない機能です。

基本的な構文

json_encode(mixed $value, int $flags = 0, int $depth = 512): string|false

基本的な使い方

配列をJSONに変換

// インデックス配列
$fruits = ['りんご', 'バナナ', 'オレンジ'];
echo json_encode($fruits);
// 出力: ["りんご","バナナ","オレンジ"]

// 連想配列
$user = [
    'name' => '田中太郎',
    'age' => 30,
    'city' => '東京',
    'hobbies' => ['読書', '映画鑑賞', 'プログラミング']
];
echo json_encode($user);
// 出力: {"name":"田中太郎","age":30,"city":"東京","hobbies":["読書","映画鑑賞","プログラミング"]}

オブジェクトをJSONに変換

class User {
    public $name;
    public $email;
    private $password; // privateプロパティは含まれない
    
    public function __construct($name, $email, $password) {
        $this->name = $name;
        $this->email = $email;
        $this->password = $password;
    }
}

$user = new User('山田花子', 'hanako@example.com', 'secret123');
echo json_encode($user);
// 出力: {"name":"山田花子","email":"hanako@example.com"}

重要なフラグオプション

JSON_UNESCAPED_UNICODE – 日本語文字の処理

$data = ['message' => 'こんにちは、世界!'];

// デフォルト(エスケープされる)
echo json_encode($data);
// 出力: {"message":"\u3053\u3093\u306b\u3061\u306f\u3001\u4e16\u754c\uff01"}

// 日本語をそのまま出力
echo json_encode($data, JSON_UNESCAPED_UNICODE);
// 出力: {"message":"こんにちは、世界!"}

JSON_PRETTY_PRINT – 読みやすい形式

$data = [
    'users' => [
        ['name' => '田中', 'age' => 25],
        ['name' => '佐藤', 'age' => 30]
    ],
    'total' => 2
];

echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

出力:

{
    "users": [
        {
            "name": "田中",
            "age": 25
        },
        {
            "name": "佐藤",
            "age": 30
        }
    ],
    "total": 2
}

JSON_NUMERIC_CHECK – 数値文字列の自動変換

$data = [
    'id' => '123',        // 文字列
    'score' => '95.5',    // 文字列
    'name' => 'テスト'
];

// 通常の変換
echo json_encode($data, JSON_UNESCAPED_UNICODE);
// 出力: {"id":"123","score":"95.5","name":"テスト"}

// 数値文字列を自動的に数値に変換
echo json_encode($data, JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE);
// 出力: {"id":123,"score":95.5,"name":"テスト"}

実践的な使用例

Web APIのレスポンス作成

<?php
header('Content-Type: application/json; charset=utf-8');

// データベースからユーザー情報を取得(仮の処理)
function getUserById($userId) {
    // 実際はデータベースから取得
    return [
        'id' => $userId,
        'name' => '田中太郎',
        'email' => 'tanaka@example.com',
        'created_at' => '2024-01-15 10:30:00',
        'profile' => [
            'age' => 30,
            'location' => '東京都',
            'bio' => 'PHPエンジニアです'
        ]
    ];
}

try {
    $userId = $_GET['id'] ?? null;
    
    if (!$userId) {
        http_response_code(400);
        echo json_encode([
            'error' => 'ユーザーIDが指定されていません'
        ], JSON_UNESCAPED_UNICODE);
        exit;
    }
    
    $user = getUserById($userId);
    
    if (!$user) {
        http_response_code(404);
        echo json_encode([
            'error' => 'ユーザーが見つかりません'
        ], JSON_UNESCAPED_UNICODE);
        exit;
    }
    
    // 成功レスポンス
    echo json_encode([
        'status' => 'success',
        'data' => $user
    ], JSON_UNESCAPED_UNICODE);
    
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode([
        'error' => 'サーバーエラーが発生しました'
    ], JSON_UNESCAPED_UNICODE);
}
?>

Ajax通信での活用

// フォーム処理スクリプト
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = $_POST['name'] ?? '';
    $email = $_POST['email'] ?? '';
    
    $errors = [];
    
    // バリデーション
    if (empty($name)) {
        $errors[] = '名前は必須です';
    }
    
    if (empty($email)) {
        $errors[] = 'メールアドレスは必須です';
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = 'メールアドレスの形式が正しくありません';
    }
    
    header('Content-Type: application/json; charset=utf-8');
    
    if (!empty($errors)) {
        echo json_encode([
            'success' => false,
            'errors' => $errors
        ], JSON_UNESCAPED_UNICODE);
    } else {
        // 保存処理(省略)
        echo json_encode([
            'success' => true,
            'message' => '登録が完了しました',
            'redirect' => '/success.php'
        ], JSON_UNESCAPED_UNICODE);
    }
}

設定ファイルの生成

$config = [
    'database' => [
        'host' => 'localhost',
        'port' => 3306,
        'name' => 'myapp',
        'charset' => 'utf8mb4'
    ],
    'cache' => [
        'enabled' => true,
        'driver' => 'redis',
        'ttl' => 3600
    ],
    'mail' => [
        'smtp_host' => 'smtp.example.com',
        'smtp_port' => 587,
        'from_address' => 'noreply@example.com'
    ]
];

// 設定ファイルとして保存
$configJson = json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
file_put_contents('config.json', $configJson);

エラーハンドリング

json_encode関数は、変換に失敗した場合にfalseを返します。適切なエラーハンドリングを実装しましょう。

function safeJsonEncode($data, $flags = 0) {
    $json = json_encode($data, $flags);
    
    if ($json === false) {
        $errorMessage = 'Unknown error';
        
        switch (json_last_error()) {
            case JSON_ERROR_DEPTH:
                $errorMessage = '最大スタック深度を超過しました';
                break;
            case JSON_ERROR_STATE_MISMATCH:
                $errorMessage = 'JSON の状態が一致しません';
                break;
            case JSON_ERROR_CTRL_CHAR:
                $errorMessage = '制御文字エラー';
                break;
            case JSON_ERROR_SYNTAX:
                $errorMessage = '構文エラー';
                break;
            case JSON_ERROR_UTF8:
                $errorMessage = 'UTF-8 エラー';
                break;
            case JSON_ERROR_RECURSION:
                $errorMessage = '再帰的な参照が検出されました';
                break;
            case JSON_ERROR_INF_OR_NAN:
                $errorMessage = 'NAN または INF の値';
                break;
            case JSON_ERROR_UNSUPPORTED_TYPE:
                $errorMessage = 'サポートされていない型';
                break;
        }
        
        throw new JsonException("JSON エンコードエラー: " . $errorMessage);
    }
    
    return $json;
}

// 使用例
try {
    $data = ['name' => '田中', 'age' => 30];
    $json = safeJsonEncode($data, JSON_UNESCAPED_UNICODE);
    echo $json;
} catch (JsonException $e) {
    echo "エラー: " . $e->getMessage();
}

特殊なデータ型の処理

DateTimeオブジェクト

class JsonSerializableUser implements JsonSerializable {
    private $name;
    private $birthDate;
    
    public function __construct($name, DateTime $birthDate) {
        $this->name = $name;
        $this->birthDate = $birthDate;
    }
    
    public function jsonSerialize(): array {
        return [
            'name' => $this->name,
            'birth_date' => $this->birthDate->format('Y-m-d'),
            'age' => $this->calculateAge()
        ];
    }
    
    private function calculateAge(): int {
        return (new DateTime())->diff($this->birthDate)->y;
    }
}

$user = new JsonSerializableUser('田中太郎', new DateTime('1990-05-15'));
echo json_encode($user, JSON_UNESCAPED_UNICODE);
// 出力: {"name":"田中太郎","birth_date":"1990-05-15","age":34}

リソース型の除外

$data = [
    'name' => 'ファイル情報',
    'handle' => fopen('test.txt', 'r'), // リソース型
    'size' => 1024
];

// リソース型は自動的に除外される
echo json_encode($data, JSON_UNESCAPED_UNICODE);
// 出力: {"name":"ファイル情報","size":1024}

// ファイルハンドルを閉じる
fclose($data['handle']);

パフォーマンス最適化

大きなデータセットの処理

// 大量データの処理例
function processLargeDataset($data) {
    $startTime = microtime(true);
    $memoryBefore = memory_get_usage();
    
    // JSON変換
    $json = json_encode($data, JSON_UNESCAPED_UNICODE);
    
    $endTime = microtime(true);
    $memoryAfter = memory_get_usage();
    
    echo "処理時間: " . ($endTime - $startTime) . "秒\n";
    echo "使用メモリ: " . ($memoryAfter - $memoryBefore) . " bytes\n";
    
    return $json;
}

// 使用例
$largeData = array_fill(0, 10000, ['id' => rand(1, 1000), 'name' => 'ユーザー']);
$json = processLargeDataset($largeData);

セキュリティ上の注意点

XSS対策

// ユーザー入力を含むデータをJSONに変換する場合
function secureJsonEncode($data) {
    // HTMLエスケープ処理
    $escapedData = array_map(function($value) {
        if (is_string($value)) {
            return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
        }
        return $value;
    }, $data);
    
    return json_encode($escapedData, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
}

$userData = [
    'name' => '<script>alert("XSS")</script>',
    'message' => 'Hello & goodbye'
];

echo secureJsonEncode($userData);

よく使用されるフラグの組み合わせ

// 開発時によく使用される組み合わせ
define('JSON_DEFAULT_FLAGS', JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);

// API レスポンス用
define('JSON_API_FLAGS', JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);

// セキュア用途
define('JSON_SECURE_FLAGS', JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP);

$data = ['message' => 'テストデータ', 'count' => '123'];

echo "開発用:\n";
echo json_encode($data, JSON_DEFAULT_FLAGS) . "\n\n";

echo "API用:\n";
echo json_encode($data, JSON_API_FLAGS) . "\n\n";

echo "セキュア用:\n";
echo json_encode($data, JSON_SECURE_FLAGS) . "\n";

まとめ

json_encode関数は、現代のPHP開発において必須の機能です。Web APIの構築、フロントエンドとの連携、設定ファイルの生成など、様々な場面で活用できます。

重要なポイント:

  • 日本語データを扱う際はJSON_UNESCAPED_UNICODEフラグを使用
  • 開発時の確認にはJSON_PRETTY_PRINTで見やすく整形
  • エラーハンドリングを適切に実装する
  • セキュリティ面では適切なエスケープ処理を行う
  • パフォーマンスを考慮して大きなデータセットは注意深く処理

これらのテクニックを身につけることで、より堅牢で効率的なPHPアプリケーションを開発できるようになります。実際のプロジェクトでぜひ活用してみてください。

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