Menu

PHPのjson_encode():配列やオブジェクトをJSONに変換

json_encode($value)は、PHPの配列、オブジェクト、スカラー値をJSONの文字列に変換します。連想配列はJSONオブジェクトに、リストはJSON配列になり、JSON_PRETTY_PRINTやJSON_UNESCAPED_UNICODEなどのフラグで出力を制御できます。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

json_encode($value)は、PHPの値をJSONのテキストにして返します。連想配列はJSONオブジェクトに、リスト(キーが0, 1, 2...)はJSON配列になり、文字列、数値、true、false、nullはそれぞれ対応するJSONの値になります。

出力:

{"name":"Ada","age":36,"langs":["php","js"],"admin":true,"manager":null}
string

結果はただの文字列で、そのままブラウザに送ったり、ファイルやデータベースのカラムに保存したり、ほかのプログラムに渡したりできます。JSONをPHPに戻すにはjson_decode()を使います。

JSONを整形して出力する

json_encode()は2つ目の引数にフラグを受け取ります。JSON_PRETTY_PRINTは改行と4つの空白のインデントを加え、設定ファイルやデバッグ用のログに向いています。複数のフラグは|で組み合わせます。

出力:

{
    "app": "shop",
    "debug": false,
    "db": {
        "host": "localhost",
        "port": 3306
    },
    "tags": []
}

日本語などのUTF-8テキストを読めるまま保つ

デフォルトでは、json_encode()はASCII以外のすべての文字を\uのエスケープで書き、すべての/の前にバックスラッシュを付けます。どちらも正しいJSONで、デコードすれば同じテキストに戻りますが、出力が読みにくく長くなります。JSON_UNESCAPED_UNICODEは文字をそのまま保ち、JSON_UNESCAPED_SLASHESはURLをそのまま保ちます。

出力:

{"name":"\u308a\u3093\u3054","price":120,"url":"https:\/\/example.com\/fruit\/apple"}
{"name":"りんご","price":120,"url":"https://example.com/fruit/apple"}

デコードしたあとに日本語が文字化けしているなら、原因はエスケープではなく、文字列がそもそもUTF-8ではなかったことです。json_encode()はUTF-8しか受け付けず、それ以外にはfalseを返します。エラーの節で示します。

配列がリストではなくオブジェクトになるとき

PHPの配列がJSON配列にエンコードされるのは、キーがちょうど0, 1, 2...と順に並んでいるときだけです。それ以外のキーではJSONオブジェクトになります。キーに欠番を残すunset()やarray_filter()のあとで、これに引っかかる人がよくいます。

出力:

{"0":"apple","2":"cherry"}
["apple","cherry"]
{"1":"a","2":"b"}
[]
{}
{"0":"a","1":"b"}

受け取る側のコードがリストを期待しているなら、エンコードする前に必ずarray_values()を呼びましょう。空かもしれないオブジェクトを期待しているなら、空の値でも{}として出力されるようnew stdClass()か(object) $arrayを使います。

オブジェクトをエンコードし、JsonSerializableでJSONを制御する

普通のオブジェクトはpublicなプロパティだけでエンコードされ、protectedとprivateのものは飛ばされます。オブジェクトがJSONでどう見えるかを正確に決めるには、JsonSerializableインターフェースを実装し、jsonSerialize()からデータを返します。

出力:

{"name":"Ada","nick":null}
{"date":"2026-03-14 09:30:00.000000","timezone_type":3,"timezone":"UTC"}
{
    "id": 7,
    "total": 19.5,
    "created": "2026-03-14T09:30:00+00:00"
}

enum Status: stringのようなBacked Enumはその値("active")としてエンコードされます。Pure Enumには値がないので、json_encode()は「Non-backed enums have no default serialization」で失敗します。

数値、浮動小数点数、数値文字列

整数と浮動小数点数はJSONの数値として書かれ、文字列は数字を含んでいても文字列のままです。3つのフラグでこれを変えられます。

出力:

{"price":10}
{"price":10.0}
0.30000000000000004
{"qty":"3","id":"007"}
{"qty":3,"id":7}

JSON_NUMERIC_CHECKはすべての数値文字列を変換するので、"007"のようなIDや"01234"のような郵便番号は先頭のゼロを失います。配列全体にこれを使うのではなく、意図したフィールドを(int)で変換しましょう。

json_encodeがfalseを返す:エラーを見つける

値をエンコードできないと、json_encode()はfalseを返します。よくある原因は、正しいUTF-8でない文字列(古いファイルやLatin-1のデータベースから読んだテキスト)と、浮動小数点数の値NANとINFです。json_last_error_msg()が何が問題かを示し、JSON_THROW_ON_ERRORを指定すると代わりにJsonExceptionが投げられます。

出力:

bool(false)
Malformed UTF-8 characters, possibly incorrectly encoded
{"name":"Caf\ufffd"}
{"name":"Café"}
JsonException: Inf and NaN cannot be JSON encoded

新しいコードではJSON_THROW_ON_ERRORのほうがよいデフォルトです。誰も確認しないfalseは、空文字列として保存されたり送信されたりしてしまいます。

PHPのAPIからJSONを返す

JSONで応答するPHPスクリプトは、何かを出力する前にContent-Typeヘッダーを設定し、1回だけエンコードして終了します。

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

$products = [
    ['id' => 1, 'name' => 'りんご', 'price' => 120],
    ['id' => 2, 'name' => 'みかん', 'price' => 80],
];

echo json_encode(['data' => $products], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
exit;

代わりにHTMLの<script>タグの中にJSONを出力するときは、JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOTを加えます。デフォルトのスラッシュのエスケープは</script>を<\/script>に変えますが、誰かがJSON_UNESCAPED_SLASHESを加えたとたんにその保護はなくなり、値の中の<!--はやはりブラウザのスクリプトの解析を変えてしまいます。これらのフラグは<、>、&、'、"を\u003C、\u003E、\u0026、\u0027、\u0022として書き、JavaScriptはそれを同じ文字として読み戻します。

よくある質問

PHPの配列をJSONに変換するには?

json_encode()に渡します:json_encode(['name' => 'Ada', 'age' => 36])は{"name":"Ada","age":36}を返します。キーが0, 1, 2...と順に並ぶ配列は、代わりにJSON配列になります:json_encode(['a', 'b'])は["a","b"]を返します。

PHPでJSONを整形して出力するには?

JSON_PRETTY_PRINTフラグを加えます:json_encode($data, JSON_PRETTY_PRINT)は4つの空白でインデントし、各値を1行ずつに置きます。フラグは|で組み合わせます。たとえばJSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODEです。

json_encodeで日本語が\uのコードになってしまうのはなぜですか?

デフォルトでは、ASCII以外のすべての文字が\uXXXXのエスケープで書かれるので、りんごは\u308a\u3093\u3054になります。それでも正しいJSONですが、文字を読めるまま保つにはJSON_UNESCAPED_UNICODEを渡します。

json_encodeがfalseを返すのはなぜですか?

たいていは、文字列が正しいUTF-8でないか、データにNANやINFが含まれているからです。json_last_error_msg()を呼んで理由を確認するか、falseを返す代わりにJsonExceptionを投げるようJSON_THROW_ON_ERRORを渡します。

空の配列に対してjson_encodeに[]ではなく{}を出力させるには?

PHPの空の配列は常に[]にエンコードされます。空のオブジェクトにはnew stdClass()か(object) []を使うか、値の中のすべての配列をオブジェクトにするJSON_FORCE_OBJECTフラグを使います。

Coddyのプログラミング言語のイラスト

Coddyでコードを学ぼう

始める