はじめに
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アプリケーションを開発できるようになります。実際のプロジェクトでぜひ活用してみてください。