PHPのjson_encode←変数→json_decodeで改行コード(LF)が含まれている場合の挙動
PHPの json_encode
と json_decode
でこれまで把握していなかった挙動を最近知ったのでメモとして残しておきます。
動作環境は PHP 7.4.28
を利用しました。
$ docker container run --rm -it php:7.4.28-cli-alpine /bin/sh
まず、改行コード(LF)を含む変数をヒアドキュメントで作成(変数 $heredoc
にセット)します。
# vi json_test.php
<?php
$heredoc =<<<EOD
12345
ABCDE
67890
FGHIJ
EOD;
var_dump($heredoc);
実行してみると、このように改行を含んだ形で変数の内容が表示されました。
# php json_test.php
string(23) "12345
ABCDE
67890
FGHIJ"
次に、先ほどの変数 $heredoc
を連想配列にセットして、 json_encode
を実行するための元ネタを作成します。
$array = [
'heredoc' => $heredoc,
];
var_dump($array);
実行してみると、このように連想配列に改行を含んだ形でセットされていることがわかります。
# php json_test.php
・
・
array(1) {
["heredoc"]=>
string(23) "12345
ABCDE
67890
FGHIJ"
}
次に、先ほど作成した連想配列を json_encode
してみましょう。
$encode = json_encode($array);
var_dump($encode);
実行してみると、改行コード(LF)が文字列の「\n」に変換されて格納されていることがわかります。これまでこの挙動を知らなかったので、なるほどなと思いました。
# php json_test.php
・
・
string(40) "{"heredoc":"12345\nABCDE\n67890\nFGHIJ"}"
それでは、 json_encode
された変数を json_decode
で元の形にもどしてみます。(連想配列の形式にするため、第2引数の associative
に true を渡します)
$decode = json_decode($encode, true);
var_dump($decode);
実行してみると、文字列の「\n」が改行コード(LF)の状態に戻っていることがわかります。
# php json_test.php
・
・
array(1) {
["heredoc"]=>
string(23) "12345
ABCDE
67890
FGHIJ"
}
では、元の変数 $heredoc
をこのように「\n」を含む形でセットしたらどうなるのでしょう?
$heredoc =<<<EOD
12345
A\nBCDE
67890
FGH\n\nIJ
EOD;
json_encode
を実行するとこうなりました。そりゃそうか。
# php json_test.php
・
・
string(46) "{"heredoc":"12345\nA\nBCDE\n67890\nFGH\n\nIJ"}"
もちろんこれを json_decode
すると、文字列の「\n」が改行コード(LF)に変換されてこうなります。 json_encode
、 json_decode
を行う際、「\n」には注意が必要ですね。
# php json_test.php
・
・
array(1) {
["heredoc"]=>
string(26) "12345
A
BCDE
67890
FGH
IJ"
}
JSONの文字列に改行コード(LF)を含んでいると、ダブルクォートで括ったときにJSONの形式が壊れるので、改行コード(LF)を「\n」に変換するような挙動になっているんだと思いますが、知っておかないとバグの原因になりそうだなと感じました。
もしかすると、 json_encode
、 json_decode
の引数「flags」で何かしら制御ができるかもしれませんが、今回そこまでは調べてません。
追記(2021/03/20)
@tadsan から「ヒアドキュメント構文」と「Nowdoc構文」で動作が違いますよ、と教えてもらいました。
php.net の説明によると、「ヒアドキュメントがダブルクォートで囲んだ文字列として扱われるのに対して、 Nowdoc はシングルクォートで囲んだ文字列として扱われます。」とのこと。
つまり、このように文字列の「\n」を含む形でNowdoc構文(終端を示す識別子をシングルクォートで囲む)で定義して、
<?php
$nowdoc =<<<'EOD'
12345
A\nBCDE
67890
FGH\n\nIJ
EOD;
var_dump($nowdoc);
実行してみると、Nowdoc構文はシングルクォートで囲んだ文字列として扱われるので「\n」は「\n」のまま出力されます。(改行コード(LF)には変換されません)
php json_test.php
string(29) "12345
A\nBCDE
67890
FGH\n\nIJ"
変数 $nowdoc
に対して json_encode
を実行してみると、
$array = [
'nowdoc' => $nowdoc,
];
$encode = json_encode($array);
var_dump($encode);
文字列の「\n」は「\\n」とエスケープされ、改行コード(LF)は「\n」となります。
string(48) "{"nowdoc":"12345\nA\\nBCDE\n67890\nFGH\\n\\nIJ"}"
Author And Source
この問題について(PHPのjson_encode←変数→json_decodeで改行コード(LF)が含まれている場合の挙動), 我々は、より多くの情報をここで見つけました https://qiita.com/akase244/items/703daee32765381055fd著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .