何をしたいユーティリティなのか
「JSON → 配列(型安全)」は、 文字列として渡されてきた JSON を「PHP の配列」に変換するときに、
- ちゃんと JSON として正しいかチェックする
- 期待している“形・型”になっているか確認する
ところまでをセットでやってくれるユーティリティです。
ただ json_decode するだけだと、
- 間違った JSON でも
nullが返って終わり - 数値だと思っていたら文字列だった
- 配列だと思っていたらオブジェクトだった
みたいな「型のズレ」が、あとからバグの原因になります。 そこを最初にきっちりチェックしておくのが「型安全」な JSON → 配列変換です。
まずは json_decode の基本を押さえる
json_decode のよくある使い方
PHP には json_decode があります。
$json = '{"id":123,"name":"Taro"}';
$data = json_decode($json, true);
var_dump($data);
PHP第 2 引数に true を渡すと、「連想配列として」デコードされます。
結果はこうです。
array(2) {
["id"] => int(123)
["name"] => string(4) "Taro"
}
PHPここまではよく見る使い方ですが、 実務ではもう少し気をつけたいポイントがあります。
エラー時の挙動
間違った JSON を渡すと、json_decode は null を返します。
$json = '{"id":123,"name":"Taro"'; // 末尾の } がない
$data = json_decode($json, true);
var_dump($data); // NULL
PHP「ただの NULL」と「JSON として失敗した NULL」が区別できないと、 あとから「なんでここ NULLなんだっけ?」と迷子になります。
そこで、「エラーをちゃんと検知する」書き方が必要になります。
型安全の第一歩:「エラーを例外で知らせる」ユーティリティ
json_decode に JSON_THROW_ON_ERROR を付ける
PHP 7.3 以降では、json_decode に JSON_THROW_ON_ERROR フラグを付けると、 エラー時に例外を投げてくれます。
function decode_json_to_array(string $json): array
{
try {
$data = json_decode(
$json,
true, // 連想配列として
512, // 最大深さ(デフォルト)
JSON_THROW_ON_ERROR
);
} catch (JsonException $e) {
// 実務ではここでログを出したり、別の例外に包んだりする
throw new RuntimeException('JSON decode failed: ' . $e->getMessage(), 0, $e);
}
// 念のため、配列であることを確認
if (!is_array($data)) {
throw new RuntimeException('Decoded JSON is not an array');
}
return $data;
}
PHPここでの重要ポイントは 2 つです。
- JSON_THROW_ON_ERROR で「間違った JSON」を例外として検知できること
is_arrayで「配列として扱える形か」を確認していること
これで、「JSON としておかしい」「配列じゃない」というケースを、 呼び出し側にきちんと伝えられるようになります。
例題で挙動を確認する
正しい JSON の場合
$json = '{"id":123,"name":"Taro"}';
$data = decode_json_to_array($json);
var_dump($data);
PHP結果はこうです。
array(2) {
["id"] => int(123)
["name"] => string(4) "Taro"
}
PHP普通に連想配列として扱えます。
間違った JSON の場合
$json = '{"id":123,"name":"Taro"'; // 末尾の } がない
$data = decode_json_to_array($json); // RuntimeException が投げられる
PHPこのときは、RuntimeException('JSON decode failed: ...') が投げられます。 「失敗したこと」がはっきり分かるので、 呼び出し側で try/catch して、エラーメッセージを出したり、ログに残したりできます。
型安全の第二歩:「中身の型・形をチェックする」
期待する構造を決める
例えば、「ユーザー情報の JSON」を受け取るとします。
期待する形はこうだと決めます。
id… 整数name… 文字列tags… 文字列の配列
この「期待する形」に合っているかをチェックするのが、型安全の次のステップです。
チェック付きのユーティリティを作る
/**
* ユーザー情報 JSON を「型安全な配列」にデコードする
*
* 期待する形:
* {
* "id": int,
* "name": string,
* "tags": string[]
* }
*/
function decode_user_json(string $json): array
{
$data = decode_json_to_array($json);
// id が存在し、整数であること
if (!array_key_exists('id', $data) || !is_int($data['id'])) {
throw new RuntimeException('Invalid JSON: "id" must be int');
}
// name が存在し、文字列であること
if (!array_key_exists('name', $data) || !is_string($data['name'])) {
throw new RuntimeException('Invalid JSON: "name" must be string');
}
// tags が存在し、配列であること
if (!array_key_exists('tags', $data) || !is_array($data['tags'])) {
throw new RuntimeException('Invalid JSON: "tags" must be array');
}
// tags の中身がすべて文字列であること
foreach ($data['tags'] as $tag) {
if (!is_string($tag)) {
throw new RuntimeException('Invalid JSON: "tags" must be array of string');
}
}
return $data;
}
PHPここでの重要ポイントは、「期待する型をコードで明示している」ことです。
idは int じゃないとダメnameは string じゃないとダメtagsは配列で、その中身も string じゃないとダメ
こうしておくと、「型が違う JSON」が来たときにすぐに分かります。
例題:型がズレている JSON を検知する
id が文字列になっている場合
$json = '{"id":"123","name":"Taro","tags":["php","backend"]}';
$data = decode_user_json($json); // RuntimeException: "id" must be int
PHPjson_decode 自体は成功しますが、 id が文字列なので、型チェックで弾かれます。
tags の中に数値が混ざっている場合
$json = '{"id":123,"name":"Taro","tags":["php", 100]}';
$data = decode_user_json($json); // RuntimeException: "tags" must be array of string
PHPtags の 2 番目が数値なので、 「文字列の配列」という期待に合わず、例外になります。
こうして「型のズレ」を早い段階で検知しておくと、 後の処理で「想定外の型」によるバグが起きにくくなります。
実務での使いどころ
外部 API からのレスポンスを扱うとき
外部 API から JSON が返ってきて、それを配列として扱うケースはよくあります。
$responseJson = $client->getBody();
try {
$user = decode_user_json($responseJson);
} catch (RuntimeException $e) {
// レスポンスがおかしいのでログに残して、処理を中断する
error_log('Invalid user JSON: ' . $e->getMessage());
// 必要ならユーザー向けエラーを返す
}
PHP「レスポンスがおかしい」ことを早めに検知できるので、 変なデータをそのまま DB に保存してしまう、といった事故を防げます。
設定ファイル(JSON)を読み込むとき
設定を JSON ファイルで持っていて、 起動時に読み込むようなケースでも同じです。
$json = file_get_contents(__DIR__ . '/config.json');
$config = decode_json_to_array($json);
// ここでさらに「必須キーがあるか」「型が合っているか」をチェックする
PHP設定の型がズレていると、 本番環境でだけ変な挙動をする、という怖いバグにつながります。 型安全なデコードをしておくことで、そのリスクを減らせます。
まとめ:今日からの「JSON → 配列(型安全)」ユーティリティ
このユーティリティの本質は、「JSON をただ配列にするだけじゃなく、“期待する形・型”まで保証してあげる」ことです。
そのために、
- JSON_THROW_ON_ERROR で「JSON としてのエラー」を例外で検知する
is_arrayで「配列として扱えるか」を確認する- 必須キーの存在と、各キーの型をチェックする
という処理を、ユーティリティ関数に閉じ込めておきます。
もう一度、基本形を載せておきます。
function decode_json_to_array(string $json): array
{
try {
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
throw new RuntimeException('JSON decode failed: ' . $e->getMessage(), 0, $e);
}
if (!is_array($data)) {
throw new RuntimeException('Decoded JSON is not an array');
}
return $data;
}
PHPそして、必要に応じて「期待する構造ごとに専用のチェック関数」を作っていく。 それだけで、JSON 周りのバグと「よく分からない NULL」に悩まされることが、ぐっと減ります。
