PHPのjson_decodeの使い方とnullになる原因|配列変換・エラー処理をサンプルコード付きで解説

基本文法・構文ガイド

json_decodeで「nullが返ってくる」「エラーの原因がわからない」——公式マニュアルだけでは分かりにくいそんなつまずきに、コピペで使えるサンプルコード付きで答える記事です。json_decodeは、JSON文字列を配列やオブジェクトに変換する関数で、第2引数にtrueを渡すかどうかで戻り値の型が変わり、JSON文字列に問題があるとnullを返します。この記事では、配列・オブジェクトへの変換方法から、nullになる原因の切り分け方、json_last_errorを使ったエラー処理まで実例付きで解説します。

json_decodeで配列に変換する方法

JSONを配列として受け取るには、第2引数に true を指定します。これが最もよく使う基本形です。

$json = '{"name": "Taro", "age": 25}';

$data = json_decode($json, true);

echo $data['name']; // Taro
echo $data['age'];  // 25

第2引数に true を渡すのがポイントです。省略すると配列ではなくオブジェクトとして返ります。

多次元配列の例

ネストされたJSONも true を指定すれば入れ子の連想配列として取得できます。

$json = '{
    "user": {
        "name": "Taro",
        "address": {
            "city": "Tokyo",
            "zip": "100-0001"
        }
    },
    "tags": ["php", "json", "laravel"]
}';

$data = json_decode($json, true);

echo $data['user']['name'];             // Taro
echo $data['user']['address']['city'];  // Tokyo
echo $data['tags'][0];                  // php

JSON配列([])はPHPの添字配列、JSONオブジェクト({})は連想配列にそれぞれ対応します。

JSONとは

JSONは、データ構造を持つオブジェクトを簡潔に表現するためのフォーマットで、特にウェブサービスやAPIのレスポンスで利用されています。例えば、RESTful APIからデータを取得する際、JSONフォーマットで送信されることが多いです。JSONは、以下のようなキーと値のペアでデータを表現します。

{
    "name": "John Doe",
    "age": 30,
    "isEmployed": true
}

PHPでJSONを扱う理由

JSONはその軽量さと柔軟性から、異なるプラットフォーム間でデータを交換する際に非常に便利です。PHPでは、JSONを扱うための組み込み関数が用意されており、その中でもjson_decodeを使用することで、JSONデータをPHPのネイティブなデータタイプに変換することができます。

json_decodeの基本的な使い方

json_decode関数は、JSON文字列をPHPの連想配列またはオブジェクトに変換するための関数です。以下に基本的な使用法を示します。

$jsonData = '{"name": "John Doe", "age": 30, "isEmployed": true}';

$array = json_decode($jsonData, true); // 連想配列に変換
$object = json_decode($jsonData);      // オブジェクトに変換

print_r($array);
print_r($object);

配列とオブジェクトの違い

第2引数の指定によって戻り値の型が変わります。それぞれの特徴を整理します。

第2引数 戻り値の型 値へのアクセス 主な用途
true 連想配列(array) $data['key'] 一般的なデータ処理、Laravelでよく使う
false(デフォルト) stdClassオブジェクト $data->key オブジェクト指向で扱いたい場合
$json = '{"name": "John", "age": 30}';

// 配列として受け取る
$array = json_decode($json, true);
echo $array['name']; // John

// オブジェクトとして受け取る
$object = json_decode($json);
echo $object->name; // John

実務では true を指定して配列で受け取るほうが配列関数と相性が良く、コードが読みやすくなるためよく使われます。逆にPHPの配列やオブジェクトをJSON文字列に変換したい場合はjson_encodeを使います。使い方や注意点は「PHPでjson_encodeを使ってデータをJSON形式に変換する方法と注意点」で解説しています。

第一引数: JSON文字列

最初の引数には、変換したいJSON形式の文字列を指定します。この文字列が有効なJSON形式でない場合、json_decodenullを返し、その旨のエラーメッセージが発生します。

第二引数: 結果を配列にするかオブジェクトにするか

第二引数は省略可能で、デフォルトではfalseとして扱われます。trueを指定すると、JSONデータは連想配列として変換され、falseまたは省略した場合は、PHPのオブジェクトとして変換されます。このため、デコード後にデータをどのようにアクセスしたいかによって設定を変更します。

JSON配列のデコード

JSON形式では、配列も表現可能です。例えば、以下のようなJSON配列を考えます:

[
    {"name": "John Doe", "age": 30},
    {"name": "Jane Smith", "age": 25}
]

このJSON配列をデコードし、PHPの連想配列としてアクセスする例を以下に示します。

$jsonArray = '[{"name": "John Doe", "age": 30}, {"name": "Jane Smith", "age": 25}]';
$array = json_decode($jsonArray, true);

foreach ($array as $person) {
    echo "Name: " . $person['name'] . ", Age: " . $person['age'] . "\n";
}

nullになる原因

json_decodenull を返す場合、JSON文字列に問題があります。主な原因と対処法を整理します。

JSON形式が不正

中括弧や角括弧の閉じ忘れ、コロンの欠落などの構文エラーです。

// NG: 閉じ括弧が欠けている
$json = '{"name": "John"';
var_dump(json_decode($json, true)); // NULL

文字コードの問題

json_decode はUTF-8のみを受け付けます。Shift_JISやEUC-JPなどの文字コードが混入すると null になります。

// Shift_JIS文字列が含まれる場合は事前に変換が必要
$json = mb_convert_encoding($sjisJson, 'UTF-8', 'SJIS');
$data = json_decode($json, true);

深さ制限(デフォルト512)

ネストが深すぎる場合は null が返ります。第3引数でフラグ、第4引数で深さを変更できます。

// 深さ上限を1024に拡張
$data = json_decode($json, true, 1024);

末尾カンマ

JSONの仕様では末尾カンマは許可されていません。JavaScriptでは動作することがあるため混入しやすいです。

// NG: 末尾カンマが含まれる
$json = '{"name": "John", "age": 30,}';
var_dump(json_decode($json, true)); // NULL

シングルクォートの使用

JSONの文字列はダブルクォートで囲む必要があります。シングルクォートを使うと無効なJSONになります。

// NG: シングルクォートは無効
$json = "{'name': 'John'}";
var_dump(json_decode($json, true)); // NULL

// OK: ダブルクォートを使う
$json = '{"name": "John"}';
var_dump(json_decode($json, true)); // array(1) { ["name"]=> string(4) "John" }

エラーハンドリング

JSONのデコード中にエラーが発生することもあります。例えば、無効なJSON文字列やエンコードされた部分の不整合などがあげられます。

json_last_error() と json_last_error_msg() の使い方

json_last_error() でエラーコードを、json_last_error_msg() で人が読めるエラーメッセージを取得できます。

$jsonData = '{"name": "John Doe", "age": 30'; // 不完全なJSON
$result = json_decode($jsonData, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    echo 'エラーコード: ' . json_last_error() . "\n";
    echo 'エラー内容: ' . json_last_error_msg() . "\n";
    // エラーコード: 4
    // エラー内容: Syntax error
}

主なエラーコードの一覧です。

定数 内容
JSON_ERROR_NONE 0 エラーなし
JSON_ERROR_DEPTH 1 最大スタック深さを超えた
JSON_ERROR_STATE_MISMATCH 2 不正またはフォーマット不正なJSON
JSON_ERROR_CTRL_CHAR 3 制御文字エラー
JSON_ERROR_SYNTAX 4 構文エラー
JSON_ERROR_UTF8 5 UTF-8文字でない文字が含まれる

JSON_THROW_ON_ERROR を使う

PHP 7.3以降では JSON_THROW_ON_ERROR フラグを使うとエラー時に例外 (JsonException) がスローされます。try-catchで処理でき、json_last_error() を都度確認する必要がなくなります。

try {
    $data = json_decode('invalid json', true, 512, JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
    echo 'JSONデコード失敗: ' . $e->getMessage(); // Syntax error
}

APIレスポンスを処理するなど、失敗が許容できないケースでは JSON_THROW_ON_ERROR を使うのが推奨です。基礎的なエンコード・デコードの操作例をもう一度おさらいしたい場合は「初心者向け:PHPでJSONデータを簡単に操作する方法と活用事例」も参考になります。

LaravelでJSONを変換する方法

LaravelではPHPの json_decode() を直接使う場面も多いですが、フレームワーク固有の機能を使うことでより簡潔に書けるケースがあります。json_decode() はPHP標準の低レイヤー関数であるのに対し、Laravelは $request->json() やEloquent castなど、アプリケーション向けの抽象化を提供しています。

RequestのJSON取得

クライアントがJSON形式でPOSTリクエストを送ってきた場合、$request->json() または $request->input() で値を取得できます。内部で自動的に json_decode が行われるため、手動で変換する必要はありません。

// Content-Type: application/json のリクエストの場合
public function store(Request $request)
{
    $name = $request->input('name');       // 単一フィールドの取得
    $data = $request->json()->all();       // 全フィールドを配列で取得
    $email = $request->json('user.email'); // ネストしたキーもドット記法で取得可能
}

Eloquent castでJSONカラムを配列にする

モデルの $casts プロパティを使うと、DBに保存したJSON文字列を取得時に自動で配列に変換できます。保存時は逆に配列を自動でJSON文字列に変換してくれるため、手動で json_decode / json_encode を呼ぶ必要がありません。

class User extends Model
{
    protected $casts = [
        'settings' => 'array', // 取得時に自動でjson_decode、保存時に自動でjson_encode
    ];
}

// 使用例
$user = User::find(1);
$theme = $user->settings['theme']; // DBのJSON文字列が配列として返る

// 保存時も配列のまま渡せる(自動でJSON文字列に変換される)
$user->settings = ['theme' => 'dark', 'lang' => 'ja'];
$user->save();

注意点: 取得済みの配列の一部だけを書き換えて$user->settings['theme'] = 'dark';のように直接キーを更新しても、Eloquentの変更検知が働かずsave()しても反映されないことがあります。安全に更新するには、いったん配列ごと取得してから書き換え、配列ごと再代入してください。

APIレスポンスとしてJSONを返す

LaravelのコントローラーからクライアントへJSONを返す場合は response()->json() を使います。自動的に Content-Type: application/json ヘッダーが付与されます。

public function index()
{
    $users = User::all();

    return response()->json([
        'data' => $users,
        'count' => $users->count(),
    ]);
}

// HTTPステータスコードを指定する場合
public function store(Request $request)
{
    $user = User::create($request->validated());

    return response()->json($user, 201);
}

外部APIのレスポンスからJSONを取得する

外部APIのレスポンスを処理する場合は Http ファサードを使うと便利です。json() メソッドで自動的に配列に変換されます。

use Illuminate\Support\Facades\Http;

$response = Http::get('https://api.example.com/users');
$users = $response->json(); // json_decode($body, true) と同等

foreach ($users as $user) {
    echo $user['name'] . "\n";
}

Laravelを使わないプレーンなPHPで外部のJSONファイルを読み込みたい場合は、file_get_contents と組み合わせるのが定番です。取得したJSON文字列をそのまま json_decode に渡すだけで配列に変換できます。詳しい使い方は「file_get_contents — ファイル/URLの内容を文字列で一括取得」で解説しています。

toArray() / toJson() / json_decode() の違い

Laravelでデータを変換する際の主要なメソッドの役割を整理します。

メソッド 役割 入力 出力 主な用途
json_decode($json, true) JSON文字列 → 配列に変換 JSON文字列 配列(array) 外部APIのレスポンス処理、JSONファイルの読み込み
$model->toArray() Eloquentモデル → 配列に変換 Eloquentモデル 配列(array) レスポンスの整形、テスト、配列操作
$model->toJson() Eloquentモデル → JSON文字列に変換 Eloquentモデル JSON文字列 JSON文字列として直接出力・保存する場合
$user = User::find(1);

// EloquentモデルをPHP配列に変換
$array = $user->toArray();
// ['id' => 1, 'name' => 'Taro', ...]

// EloquentモデルをJSON文字列に変換
$json = $user->toJson();
// '{"id":1,"name":"Taro",...}'

// JSON文字列をPHP配列に変換(PHP標準関数)
$data = json_decode($json, true);
// ['id' => 1, 'name' => 'Taro', ...]

よくある質問

json_decodeとは?

json_decode はPHPの組み込み関数で、JSON形式の文字列をPHPの配列またはオブジェクトに変換します。APIやファイルから受け取ったJSONデータをPHPで扱えるようにするために使います。第2引数に true を指定すると連想配列、省略またはfalseを指定するとstdClassオブジェクトとして返ります。

json_decodeで配列にするには?

第2引数に true を指定します。

$data = json_decode($json, true); // 連想配列として返る
echo $data['key'];

省略した場合はオブジェクトとして返るため、$data->key でアクセスする必要があります。

trueを付ける意味は?

第2引数の true は、JSONオブジェクトをPHPの連想配列として変換するフラグです。false または省略した場合は stdClass オブジェクトとして返ります。

$json = '{"key": "value"}';

$array  = json_decode($json, true);  // ['key' => 'value']
$object = json_decode($json, false); // stdClass { key: 'value' }

オブジェクトと配列の違いは?

戻り値の型とアクセス方法が異なります。実務では配列(true 指定)を使うことが多いです。

項目 配列(true指定) オブジェクト(省略)
array stdClass
アクセス $data['key'] $data->key
配列関数 array_maparray_filter 等が使える 使えない(変換が必要)
Laravelとの相性 良い(collect() 等でそのまま使える) 変換が必要な場合がある

nullになる原因は?

json_decodenull を返す主な原因は以下のとおりです。

  • JSON文字列の構文エラー(括弧の閉じ忘れ、末尾カンマなど)
  • シングルクォートを使用している(JSONはダブルクォートのみ有効)
  • UTF-8以外の文字コードが含まれている
  • ネストの深さが制限(デフォルト512)を超えている

json_last_error_msg() を呼び出すと具体的なエラー内容を確認できます。

LaravelでJSONを配列に変換するには?

場面によって使う方法が変わります。

  • リクエストのJSONを取得する場合: $request->json()->all() または $request->input('key') を使います。手動で json_decode する必要はありません。
  • 外部APIのレスポンスを変換する場合: Http::get(...)->json() で自動的に配列として取得できます。
  • JSON文字列を手動で変換する場合: json_decode($json, true) を使います(第2引数 true が必須)。
// リクエストから
$data = $request->json()->all();

// 外部APIから
$data = Http::get('https://api.example.com/data')->json();

// 文字列から
$data = json_decode($jsonString, true);

EloquentのJSONカラムはどう扱う?

モデルの $casts'column_name' => 'array' を定義するのが推奨の方法です。取得時に自動で配列に変換、保存時に自動でJSON文字列に変換されるため、アプリケーションコード上は常にPHP配列として扱えます。

class Product extends Model
{
    protected $casts = [
        'options' => 'array',
    ];
}

$product = Product::find(1);
$color = $product->options['color']; // 配列として直接アクセス

$product->options = ['color' => 'red', 'size' => 'L'];
$product->save(); // 自動的にJSON文字列として保存される

toArrayとtoJsonの違いは?

toArray() はEloquentモデルをPHP配列に変換します。配列操作や他のLaravel機能(collect() など)と組み合わせて使いたい場合に向いています。toJson() はモデルをJSON文字列に変換します。APIレスポンスとして文字列出力が必要な場合や、ファイルへの書き込みに向いています。なお response()->json($model) とすれば内部で自動的に変換されるため、どちらも明示的に呼ぶ必要はありません。

$user = User::find(1);

$user->toArray();  // PHP配列 → collect() や array_map() でそのまま使える
$user->toJson();   // JSON文字列 → そのまま出力・保存できる

// APIレスポンスでは response()->json() に渡すだけでOK
return response()->json($user); // 内部で toArray() → json_encode が行われる

まとめ

json_decode関数は、PHPでJSONを扱う上で非常に重要です。第2引数で配列・オブジェクトを使い分け、json_last_error()JSON_THROW_ON_ERROR でエラーを適切にハンドリングしましょう。Laravelを使っている場合は、場面に応じてフレームワーク機能を使い分けるのがポイントです。リクエストのJSONには $request->json()、DBのJSONカラムにはEloquent castの 'array'、レスポンスには response()->json()、外部APIには Http::get()->json() を使うと、json_decode を直接呼ぶより簡潔で安全なコードになります。toArray() はモデルをPHP配列に変換し、toJson() はJSON文字列に変換します。この使い分けを覚えておくと、LaravelでのJSON変換に迷うことがなくなります。

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする

コメント