PHPのJSON_encodeの日本語の文字化け対策!正しいオプション

[PR]

PHP

PHPでjson_encodeを使って日本語を含むデータを扱うとき、uXXXX形式で出力されて文字化けして見えることがあります。見た目だけでなく、文字コードが正しくないためにjson_decodeで失敗するケースもあります。この問題を根本から解決するためには、PHPの文字エンコーディング設定、ファイル保存形式、データベース接続、json_encodeのオプション指定など複数の要素を正しく設定することが必要です。この記事では「PHP JSON_encode 日本語 文字化け 対策」という観点で、最新情報をもとに具体的な対策を丁寧に解説します。

PHP JSON_encode 日本語 文字化け 対策の基本原則

日本語の文字化けを防ぐためには、複数のレイヤーでエンコーディングを統一する必要があります。まず、文字列データが内部的にUTF-8であることが前提です。もしデータが他のエンコーディング(例:ISO-8859-1やShift-JIS)であれば、json_encodeがInvalid UTF-8として扱ったり、uXXXX形式でエスケープされたりする原因になります。PHPの設定やデータベース、ファイル保存形式をすべてUTF-8(できればUTF-8 without BOM)に揃え、HTTPヘッダやHTML metaタグでも同様にUTF-8を指定することがまず第一歩です。経路のどこかでエンコーディングが異なると文字化けの原因になりますから、それぞれのレイヤーをチェックし、統一することが基本です。

ファイルの保存形式をUTF-8無BOMで統一する

PHPファイル自体がUTF-8で保存され、BOMが含まれない形式であることがとても重要です。BOM付きの場合、PHPが出力前に見えないバイトを挿入してしまい、HTTPヘッダの送信に失敗したり、文字列の先頭が変になったりすることがあります。エディターで「Save with Encoding」を使ってUTF-8(without BOM)形式に保存することを推奨します。これによりソースコード中のコメントや文字列リテラルに日本語を含めても予期しない文字化けが発生しにくくなります。

PHP内部の文字エンコーディング設定を確認・設定する

PHPの文字列操作関数(例えばmb_*系)やjson_encodeが期待する文字コードを内部で正しく扱うために、mb_internal_encodingをUTF-8に設定することや、default_charsetをUTF-8にすることが有効です。これらを設定することでPHPの実行環境がUTF-8で動作するようになり、文字化けの発生確率を大きく下げられます。設定はプロジェクトの入り口となるファイルで明示的に行うことが望ましいです。

データベース接続やテーブルの文字セットをutf8mb4などに統一する

データベースとのやり取りで文字コードが異なると、PHPに渡される文字列がUTF-8ではない場合があります。MySQLなどを使っている場合、接続時にutf8mb4を指定し、テーブルやカラムの文字セットもutf8mb4_unicode_ciまたはutf8mb4_general_ciなどを使うことが望ましいです。SET NAMES utf8mb4を使用したり、ORMの設定でutf8mb4を指定するなどの手順を取るとよいでしょう。

json_encodeのオプションで日本語のエスケープを防ぐ具体策

json_encode関数には、デフォルトでは日本語などのマルチバイト文字をuXXXX形式でエスケープする動作があります。これを防ぐための最も重要なオプションがJSON_UNESCAPED_UNICODEです。このオプションを指定することで、日本語がそのままUnicodeとして出力され、見た目の文字化けや扱いの違いを避けられます。さらに、JSON_INVALID_UTF8_IGNOREやJSON_INVALID_UTF8_SUBSTITUTEなどのフラグも加えることで、不正なUTF-8シーケンスを無視または代替して処理を続けることが可能です。

JSON_UNESCAPED_UNICODEの使用方法

json_encodeでUnicodeエスケープを防ぐには、第2引数にJSON_UNESCAPED_UNICODEを指定します。このフラグを使うと、日本語の文字列が「uXXXX」の形式ではなく、そのままの文字列として出力されます。例えば “あいうえお” がそのまま “あいうえお” としてJSON出力されます。このオプションはPHP 5.4以降でサポートされており、最新バージョンでも使用可能です。見た目の可読性も高まり、クライアント側での扱いも自然になります。

不正な UTF-8 バイトを処理するフラグ

json_encodeでは、入力文字列が正しいUTF-8でない場合、警告が出たり、出力がnullになったりすることがあります。こういった場合に役立つのがJSON_INVALID_UTF8_IGNOREおよびJSON_INVALID_UTF8_SUBSTITUTEというフラグです。前者は不正なバイトを無視し、後者は置換文字で代替します。JSON_UNESCAPED_UNICODEとこれらを組み合わせることで、文字化けや出力エラーを抑えつつ、日本語を含む文字列を安定して処理できます。

複数のオプションを組み合わせて使う例

日本語対応を完璧にするためには、複数のフラグを組み合わせて指定することが効果的です。例えば JSON_UNESCAPED_UNICODE と JSON_INVALID_UTF8_SUBSTITUTE や JSON_UNESCAPED_SLASHES、JSON_PRETTY_PRINT などを同時に指定して、見た目と安全性を両立させます。このような組み合わせにより、文字化けだけでなくスラッシュのエスケープや空の配列/オブジェクトの扱いなども制御できます。適切なフラグを用途に応じて選ぶことが鍵となります。

実践的なコード例とトラブルシューティング

具体的なケースを想定して、文字化けが起きる状況、その原因、対策コードを解説します。見落としがちな原因も含め、デバッグ時のチェックポイントを紹介します。実際に動かして検証した情報をもとに整理しており、様々な環境で役立つ最新情報となっています。

文字化けサンプルが出る環境例と原因の分類

例えば、ファイル保存がShift-JIS、データベースがlatin1、PHP設定がISO-8859-1という混在環境では、日本語が正しくUTF-8でないため、json_encodeでuXXXX形式にエスケープされたり、INVALID UTF-8エラーが出たりします。原因は「ソースファイル」「DB」「PHPの内部文字列」「HTTPレスポンスヘッダ」「HTMLのmetaタグ」など、複数のレイヤーにあります。まずどの部分がUTF-8として動いていないかを特定することが重要です。

コード例:統一して対策済みの実装例

次のようなコードを入口ファイル(例えば index.php)に記述すると、多くの文字化けを防げます。
header 関数で Content-Type を正しく指定し、mb_internal_encoding と default_charset を UTF-8 に設定。データベース接続時に utf8mb4 を使い、json_encode には JSON_UNESCAPED_UNICODE と JSON_INVALID_UTF8_SUBSTITUTE を指定。

例:

$​data = [‘テキスト’ => ‘日本語を含む文字列’];
header(‘Content-Type: application/json; charset=utf-8’);
mb_internal_encoding(‘UTF-8’);
ini_set(‘default_charset’, ‘UTF-8’);
// DB 接続設定で utf8mb4 を使用
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);

デバッグのためのチェックポイント

文字化けが起きるときには以下を順番に確認します。

  • ソースファイルが UTF-8 無 BOM で保存されているか
  • PHP の内部エンコーディング設定(mb_internal_encoding, default_charset)が UTF-8 か
  • HTTP レスポンスヘッダと HTML meta タグで charset=UTF-8 が正しく指定されているか
  • データベース接続とテーブル・カラムの文字セットが utf8mb4 など UTF-8 系であるか
  • json_encode に必要なオプション(JSON_UNESCAPED_UNICODE など)が使用されているか
  • 入力データに不正な UTF-8 バイトが含まれていないか

ケース別対策:特定のシーンでの応用

ケースによっては、より細かい対策が必要になります。API で使う JSON 出力、ファイルへの JSON 保存、JavaScript やAjax 通信との連携など、環境ごとの注意点があります。ここではそれぞれのシーンで頻発する問題とその解決方法を整理します。

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

API を通して JSON を返すときは、HTTP ヘッダが最も重要です。Content-Type ヘッダに application/json; charset=utf-8 を含めること。ヘッダは何か出力する前に送ること。json_encode のオプションで Unicode エスケープを防ぎ、INVALID_UTF8 系のフラグも指定すると、クライアント側で日本語が正しく扱われやすくなります。

データをファイルに保存する場合(JSONファイル)

JSON ファイルを書き出す場合はファイルのエンコーディングが UTF-8(無 BOM)であることを確認し、保存時に BOM を含めないようにします。保存処理で fopen や file_put_contents を使う際、文字列が UTF-8 であることを保証し、json_encode のオプションを適切に付与します。環境によっては BOM が付いてしまうエディターやツールがあるため要注意です。

JavaScript との通信や Ajax の利用時

フロントエンドと連携する場合、レスポンスが正しい UTF-8 で送られていないと JS 側で文字化けしたり parse が失敗したりします。サーバー側は JSON を返す前に charset ヘッダも正しく、出力バッファリングなどで余計な空白や BOM を含めないようにします。クライアント側でも charset 設定を意識し、AJAX のデフォルトヘッダや fetch/XHR の設定を確認します。

よくある誤解と注意すべきポイント

文字化け対策をしていても、思わぬ落とし穴が残っていることがあります。設定しても直らないケース、混在環境で起こる問題など、実際によく発生する誤解とその回避方法について整理します。

「ファイルが UTF-8 と言ってるが実際は違う」が起こる理由

エディターで UTF-8 と表示されていても BOM が付いていたり、中身のバイト列が正しい UTF-8 でなかったりすることがあります。たとえば古いコード生成ツールからの出力や、外部 API/ファイルの読み込みで encoding が異なるデータをそのまま使うと内部で不正 UTF-8 となります。そのため、mb_check_encoding などを使って検査・変換を行うことが重要です。

データベースが utf8 ではなく utf8mb4 を使うべき理由

MySQL の utf8 は最大3バイトで、絵文字や一部の漢字などが正しく扱えないことがあります。utf8mb4 を使うと最大4バイトまで対応できるため、サロゲートペアを含む文字列を扱う際に文字化けや置換文字が入る問題が解消されます。utf8mb4 を使っていない環境では、絵文字や希少な漢字で JSON 出力が不正になることがあります。

オプション指定を忘れることで起きる見た目と機能の違い

JSON_UNESCAPED_UNICODE を付けないと、日本語が uXXXX の形式でエスケープされます。見た目だけでなく、JS の parse やクライアントサイドでの扱いに影響が出ることがあります。特にフロントエンドが日本語をそのまま表示させたい/国際化対応をするプロジェクトでは、この違いがユーザー体験に影響します。オプションの指定漏れがないか、テストデータを使って確認することが必要です。

まとめ

文字化けを防ぐためには、単一の設定だけでは不十分で、ソースファイル保存形式・PHP内部文字設定・データベース文字セット・HTTP/HTMLのcharset・json_encode のオプション指定など、複数のレイヤーで UTF-8 を統一することが必須です。特に JSON_UNESCAPED_UNICODE は日本語をエスケープせずそのまま出力させる重要なフラグであり、これを使うことで見た目だけでなく処理上でも正しい日本語表現が可能になります。さらに、json_encode における不正 UTF-8 の処理用フラグと、ファイルの BOM による影響にも注意することで、多くのトラブルを未然に防げます。これらの対策を組み合わせて実践することで、PHP プロジェクトでの「JSON_encode 日本語 文字化け」を強力に抑えられます。

関連記事

特集記事

コメント

この記事へのトラックバックはありません。

TOP
CLOSE