PHPのjson_encode関数 — 配列をJSON文字列に変換する使い方

基本文法・構文ガイド

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

// 基本例
json_encode(["name" => "Taro", "age" => 25]);
// {"name":"Taro","age":25}

json_encode(["name" => "太郎"], JSON_UNESCAPED_UNICODE);
// {"name":"太郎"}(日本語をそのまま出力)

json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
// インデント付きで整形出力

PHPのjson_encode()は、配列やオブジェクトをJSON形式の文字列に変換する組み込み関数です。API開発やAJAX通信、キャッシュ用のキー生成、DBへのJSON保存など幅広い場面で使われます。ただし日本語が\uXXXX形式にエスケープされるスラッシュが\/にエスケープされる変換に失敗するとfalseを返すなど、初見だとつまずきやすい挙動もあります。この記事では基本構文からオプションフラグ、エラー処理、Laravelでの実践的な使い方まで解説します。

  1. json_encode関数とは?
    1. 引数の詳細
  2. 基本的な使い方
    1. 添字配列はJSON配列になる
    2. オブジェクトをエンコードする
    3. ネストした配列・オブジェクトの変換
  3. 出力を制御するフラグ(オプション)
    1. JSON_PRETTY_PRINT — 整形して出力する
    2. JSON_UNESCAPED_UNICODE — 日本語が\uXXXXになるのを防ぐ
    3. JSON_UNESCAPED_SLASHES — URLの/がエスケープされるのを防ぐ
    4. フラグを組み合わせる
    5. その他の主なフラグ
  4. エラー処理(falseになるケース)
    1. 主なエラーコード
    2. JSON_THROW_ON_ERROR を使う
  5. よくある落とし穴・注意点
    1. オブジェクトのprivate/protectedプロパティは出力されない
    2. 空配列は[]になる({}にしたい場合はJSON_FORCE_OBJECT)
    3. 大きな整数は環境によって精度が変わる
    4. 浮動小数点の末尾.0が消える
  6. json_encode / json_decode / serialize の使い分け
  7. Laravelでjson_encodeを使う/避ける場面
    1. APIレスポンスにはresponse()->json()
    2. EloquentモデルはtoJson()でJSON文字列に変換できる
    3. DBにJSONカラムとして保存するならEloquent cast
    4. それでもjson_encodeを直接使う場面
  8. 関連記事
  9. FAQ
    1. json_encodeで日本語が文字化けする/\uXXXXになるのはなぜ?
    2. json_encodeがfalseを返すのはどんなとき?
    3. 連想配列とオブジェクトどちらでも同じ結果になる?
    4. スラッシュ(/)がエスケープされるのを防ぐには?
    5. LaravelでEloquentモデルをそのままJSON文字列にするには?
  10. まとめ
  11. 関連記事

json_encode関数とは?

PHPのjson_encode()は、配列・オブジェクト・文字列・数値・真偽値などのPHPの値をJSON形式の文字列に変換する組み込み関数です。JSON文字列をPHPの値に戻すjson_decode()とペアで使われることが多い関数です。

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

引数の詳細

引数 必須 既定値 説明
$value mixed 必須 エンコードする値。resource型以外の任意の型を指定可能。文字列はUTF-8である必要がある
$flags int 任意 0 出力を制御するビットマスク。JSON_PRETTY_PRINTなどを|で組み合わせて指定
$depth int 任意 512 ネストの最大深度。1未満を指定するとPHP 8.0以降はValueError

⚠️ エンコード対象の文字列は必ずUTF-8である必要があります。Shift_JISやEUC-JPが混入していると変換に失敗しfalseが返ります。また戻り値は成功時string、失敗時falseなので、if ($json)のような真偽値判定ではなくif ($json === false)で厳密にチェックしてください(空文字列"""0"もfalsyになるため)。

基本的な使い方

連想配列を渡すとJSONオブジェクト、添字配列を渡すとJSON配列に変換されます。

$array = [
    "name"  => "Taro",
    "email" => "taro@example.com",
    "age"   => 25,
];

$json = json_encode($array);
echo $json;
// {"name":"Taro","email":"taro@example.com","age":25}

添字配列はJSON配列になる

$list = ["php", "laravel", "json"];

echo json_encode($list);
// ["php","laravel","json"]

オブジェクトをエンコードする

public プロパティを持つオブジェクトもそのままエンコードできます。

class Product
{
    public string $name = "Tシャツ";
    public int $price = 2980;
}

echo json_encode(new Product());
// {"name":"Tシャツ","price":2980}

ネストした配列・オブジェクトの変換

$data = [
    "user" => [
        "name" => "Taro",
        "address" => [
            "city" => "Tokyo",
            "zip"  => "100-0001",
        ],
    ],
    "tags" => ["php", "json", "laravel"],
];

echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
/*
{
    "user": {
        "name": "Taro",
        "address": {
            "city": "Tokyo",
            "zip": "100-0001"
        }
    },
    "tags": ["php", "json", "laravel"]
}
*/

出力を制御するフラグ(オプション)

第2引数の$flagsには複数のフラグを|(ビットOR)で組み合わせて指定できます。特によく使うのは次の3つです。

JSON_PRETTY_PRINT — 整形して出力する

$json = json_encode(["name" => "Taro", "age" => 25], JSON_PRETTY_PRINT);
echo $json;
/*
{
    "name": "Taro",
    "age": 25
}
*/

JSON_UNESCAPED_UNICODE — 日本語が\uXXXXになるのを防ぐ

デフォルトでは日本語などのマルチバイト文字が\uXXXX形式のエスケープシーケンスに変換されます。JSON仕様としては正しい表現ですが、ログやレスポンスをそのまま目視確認したい場合は読みにくくなります。

echo json_encode(["name" => "太郎"]);
// {"name":"太郎"}

echo json_encode(["name" => "太郎"], JSON_UNESCAPED_UNICODE);
// {"name":"太郎"}

JSON_UNESCAPED_SLASHES — URLの/がエスケープされるのを防ぐ

echo json_encode(["url" => "https://example.com/path"]);
// {"url":"https:\/\/example.com\/path"}

echo json_encode(["url" => "https://example.com/path"], JSON_UNESCAPED_SLASHES);
// {"url":"https://example.com/path"}

フラグを組み合わせる

APIレスポンスやログ出力では、この3つを組み合わせるのが定番です。

$json = json_encode(
    ["url" => "https://example.com", "name" => "田中"],
    JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
);

その他の主なフラグ

フラグ 対応バージョン 説明
JSON_NUMERIC_CHECK 数値形式の文字列を数値としてエンコードする
JSON_FORCE_OBJECT 配列でも常にJSONオブジェクト({})として出力する
JSON_PRESERVE_ZERO_FRACTION PHP 5.6.6+ 12.0のような小数を12ではなく12.0のまま出力する
JSON_PARTIAL_OUTPUT_ON_ERROR PHP 5.5.0+ 変換不可な値をエンコードできない箇所だけ0にして、失敗せず部分的に出力する
JSON_HEX_TAG / JSON_HEX_AMP / JSON_HEX_APOS / JSON_HEX_QUOT < > & ' "をそれぞれ\uXXXXにエスケープする(HTML内に直接埋め込む場合向け)
JSON_INVALID_UTF8_IGNORE / JSON_INVALID_UTF8_SUBSTITUTE PHP 7.2.0+ 不正なUTF-8バイト列を無視、または代替文字に置換して失敗させない
JSON_UNESCAPED_LINE_TERMINATORS PHP 7.1.0+ U+2028・U+2029(行区切り文字)をエスケープしない
JSON_THROW_ON_ERROR PHP 7.3.0+ 失敗時にfalseではなくJsonExceptionをスローする

エラー処理(falseになるケース)

json_encode()は変換に失敗するとfalseを返します。原因を調べるにはjson_last_error()json_last_error_msg()を使います。

$result = json_encode($value);

if ($result === false) {
    echo "JSONエンコードエラー: " . json_last_error_msg();
}

主なエラーコード

定数 内容
JSON_ERROR_NONE 0 エラーなし
JSON_ERROR_DEPTH 1 最大スタック深さを超えた
JSON_ERROR_UTF8 5 UTF-8として不正な文字が含まれる
JSON_ERROR_RECURSION 6 循環参照しているオブジェクト/配列が含まれる
JSON_ERROR_INF_OR_NAN 7 NANINFなど無限大・非数の値が含まれる
JSON_ERROR_UNSUPPORTED_TYPE 8 resource型などエンコード不可能な型が含まれる

JSON_THROW_ON_ERROR を使う

PHP 7.3以降ではJSON_THROW_ON_ERRORフラグを指定すると、失敗時にfalseではなく例外(JsonException)がスローされます。json_last_error()を都度チェックする必要がなくなり、うっかりチェックを忘れてfalseのまま処理が進む事故も防げます。

try {
    $json = json_encode($resource, JSON_THROW_ON_ERROR); // resource型はエンコード不可
} catch (\JsonException $e) {
    echo "JSONエンコード失敗: " . $e->getMessage();
    // Type is not supported
}

よくある落とし穴・注意点

オブジェクトのprivate/protectedプロパティは出力されない

json_encode()はオブジェクトのpublicプロパティのみを対象にします。private/protectedなプロパティを含めたい、またはカスタムの変換ロジックを適用したい場合はJsonSerializableインターフェースを実装します。

class Money implements \JsonSerializable
{
    public function __construct(
        private int $amount,
        private string $currency = "JPY"
    ) {}

    public function jsonSerialize(): mixed
    {
        return [
            "amount"   => $this->amount,
            "currency" => $this->currency,
        ];
    }
}

echo json_encode(new Money(1000));
// {"amount":1000,"currency":"JPY"}

空配列は[]になる({}にしたい場合はJSON_FORCE_OBJECT)

PHPの空配列[]は連想配列か添字配列か区別できないため、デフォルトではJSON配列[]として出力されます。API仕様上、空でも必ずJSONオブジェクト{}として返したい場合はJSON_FORCE_OBJECTを使うか、(object) []にキャストします。

echo json_encode([]);                        // []
echo json_encode([], JSON_FORCE_OBJECT);      // {}
echo json_encode((object) []);                // {}

大きな整数は環境によって精度が変わる

PHPのint型の範囲を超える整数は、32ビット環境や範囲外の値では浮動小数点数に変換され、末尾の桁が丸められることがあります。外部APIのID値など精度を保ちたい場合は、あらかじめ文字列として扱うのが安全です。

$id = "12345678901234567890"; // 文字列として保持
echo json_encode(["id" => $id]);
// {"id":"12345678901234567890"}(文字列のまま精度を保持できる)

浮動小数点の末尾.0が消える

12.0のような小数はデフォルトで12として出力されます。小数であることを維持したい場合はJSON_PRESERVE_ZERO_FRACTIONを指定します。

echo json_encode(["price" => 12.0]);
// {"price":12}

echo json_encode(["price" => 12.0], JSON_PRESERVE_ZERO_FRACTION);
// {"price":12.0}

json_encode / json_decode / serialize の使い分け

関数 役割 他言語との互換性 主な用途
json_encode() PHPの値 → JSON文字列 あり(言語非依存の標準フォーマット) API出力、外部連携、可読性が必要なキャッシュ・ログ
json_decode() JSON文字列 → PHPの値 あり 外部APIレスポンスの取り込み、JSONファイルの読み込み
serialize() / unserialize() PHPの値 ⇔ PHP固有形式の文字列 なし(PHP専用) PHP内部でのキャッシュ、セッション保存など他言語と連携しない用途

他言語のシステムやフロントエンドと値をやり取りする場合はjson_encode/json_decodeを、PHPのプロセス内だけで完結するデータ保存にはserialize/unserializeを使うのが基本方針です。

Laravelでjson_encodeを使う/避ける場面

Laravelではjson_encode()を直接呼ばなくても、フレームワークが内部で同等の処理を行ってくれる場面が多くあります。

APIレスポンスにはresponse()->json()

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

    return response()->json([
        "data"  => $users,
        "count" => $users->count(),
    ]);
    // 内部で toArray() → json_encode が行われ、Content-Type ヘッダーも自動付与される
}

EloquentモデルはtoJson()でJSON文字列に変換できる

$user = User::find(1);

$json = $user->toJson();
// json_encode($user->toArray()) とほぼ同等

$json = $user->toJson(JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// json_encodeと同じフラグをそのまま渡せる

DBにJSONカラムとして保存するならEloquent cast

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

$user->settings = ["theme" => "dark", "lang" => "ja"];
$user->save(); // 手動でjson_encodeを呼ぶ必要がない

それでもjson_encodeを直接使う場面

Laravelを使っていても、次のような場合はjson_encode()を直接呼びます。

  • キャッシュキーの生成(パラメータ配列をハッシュ化する下準備として)
  • Bladeテンプレート内でJavaScriptにPHPの値をそのまま渡したいとき(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG)のようにHTML埋め込み向けフラグと併用)
  • Eloquentモデルを介さない、単純な配列やDTOをJSON文字列化したいとき
<script>
    const config = <?= json_encode($config, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG) ?>;
</script>

関連記事

FAQ

json_encodeで日本語が文字化けする/\uXXXXになるのはなぜ?

文字化けではなく、JSON仕様に沿った正しいエスケープ表現です。人間が読める形式でそのまま出力したい場合はJSON_UNESCAPED_UNICODEフラグを指定してください。

echo json_encode(["name" => "太郎"], JSON_UNESCAPED_UNICODE);
// {"name":"太郎"}

json_encodeがfalseを返すのはどんなとき?

循環参照しているオブジェクト、resource型の値、NAN/INFなどのfloat、深さ上限を超えたネスト、不正なUTF-8文字列を含む場合などです。json_last_error_msg()で具体的な原因を確認できます。

連想配列とオブジェクトどちらでも同じ結果になる?

キーと値の構造が同じであれば、連想配列とpublicプロパティのみのオブジェクトは同じJSON文字列になります。ただしオブジェクトの場合、private/protectedプロパティは出力されない点に注意してください。

スラッシュ(/)がエスケープされるのを防ぐには?

JSON_UNESCAPED_SLASHESフラグを指定します。URLを含むデータをエンコードする際によく使います。

echo json_encode(["url" => "https://example.com"], JSON_UNESCAPED_SLASHES);
// {"url":"https://example.com"}

LaravelでEloquentモデルをそのままJSON文字列にするには?

$model->toJson()を使います。json_encode()と同じフラグを引数に渡せます。API出力であればresponse()->json($model)を使うほうが、ステータスコードやヘッダーの制御も含めて簡潔です。

まとめ

json_encode()関数のポイントをまとめます。

  • json_encode($value, $flags, $depth)でPHPの配列/オブジェクトをJSON文字列に変換する
  • 日本語をそのまま出力したいならJSON_UNESCAPED_UNICODE、URLの/を残したいならJSON_UNESCAPED_SLASHES、整形出力にはJSON_PRETTY_PRINTを使う
  • 失敗時はfalseを返す。=== falseで厳密にチェックするか、JSON_THROW_ON_ERRORで例外に切り替える
  • オブジェクトはpublicプロパティのみが対象。柔軟に制御したい場合はJsonSerializableを実装する
  • Laravelではresponse()->json()$model->toJson()、Eloquentの$castsを使うと、多くの場面でjson_encodeを直接呼ぶ必要がなくなる

基本形のjson_encode($array)から始め、日本語やURLを扱うときはエスケープ系のフラグを、失敗が許容できない処理ではJSON_THROW_ON_ERRORを組み合わせることで、意図しない出力やエラーの見落としを防げます。

レン (Wren)

こんにちは。レンです。

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

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

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

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

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

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

コメント