はじめに
PHPのjson_encode()
には、第2引数にJSON_PRETTY_PRINT
というオプションを与えることで、インデント付きのJSONを取得することが出来ます。
こんな具合です。
<?php
$array = array(
'Laala' => array(
'name' => 'Laala Manaka',
'serif' => 'kashikoma'
),
'Mirei' => array(
'name' => 'Mirei Minami',
'serif' => 'puri'
),
'Sophie' => array(
'name' => 'Sophie Hojo',
'serif' => 'pushu-'
)
);
echo json_encode($array, JSON_PRETTY_PRINT);
{
"Laala": {
"name": "Laala Manaka",
"serif": "kashikoma"
},
"Mirei": {
"name": "Mirei Minami",
"serif": "puri"
},
"Sophie": {
"name": "Sophie Hojo",
"serif": "pushu-"
}
}
何かと便利なこのオプションなのですが、PHP5.4以上でしか使えません。
そして筆者はこれを書いている2018年2月現在PHP5.3のプロジェクトにいます。
このオプションが必要になったのですが……使えない!
仕方なく自作した ので、コード晒しを兼ねて公開してみます。
レッツ車輪の再発明。
コード
<?php
$array = array(
'Laala' => array(
'name' => 'Laala Manaka',
'serif' => 'kashikoma'
),
'Mirei' => array(
'name' => 'Mirei Minami',
'serif' => 'puri'
),
'Sophie' => array(
'name' => 'Sophie Hojo',
'serif' => 'pushu-'
)
);
echo JsonPretty::prettyPrint(json_encode($array));
class JsonPretty
{
const INDENT = ' ';
public static function prettyPrint($json)
{
if (!is_string($json) || is_null(json_decode($json))) return false;
$json = self::_lineFeed($json);
$arrayed = explode("\n", $json);
$indentLayer = 0;
foreach ($arrayed as &$line) {
if (strpos($line, '}') !== false || strpos($line, ']') !== false) {
$indentLayer--;
}
for ($i = 0; $i < $indentLayer; $i++) {
$line = self::INDENT . $line;
}
if (strpos($line, '{') !== false || strpos($line, '[') !== false) {
$indentLayer++;
}
}
return implode("\n", $arrayed);
}
private static function _lineFeed($json)
{
$json = str_replace('{', "{\n", $json);
$json = str_replace('[', "[\n", $json);
$json = str_replace(',', ",\n", $json);
$json = str_replace(':', ": ", $json);
$json = str_replace(']', "\n]\n", $json);
$json = str_replace('}', "\n}", $json);
return $json;
}
}
{
"Laala": {
"name": "Laala Manaka",
"serif": "kashikoma"
},
"Mirei": {
"name": "Mirei Minami",
"serif": "puri"
},
"Sophie": {
"name": "Sophie Hojo",
"serif": "pushu-"
}
}
解説
やってることは単純です。
-
括弧やカンマを基準に改行する。
- 開き括弧の後で改行する
- 閉じ括弧の手前で改行する
- カンマの後で改行する
- コロンの後にスペースを入れる(ついでに)
-
各行ごとにインデントを入れる
- 開き括弧があれば、 次の行から インデントを1つ付ける
- 閉じ括弧があれば その行から インデントを1つ無くす
JSONの中にマルチバイト文字が入ることが分かっている場合は、JSON_UNESCAPED_UNICODE
と併用する必要がありますが。。。
こいつも例によってPHP5.3では動きません。 おのれ。
ただこっちは既にベストプラクティスがあるので、それを使えば良いでしょう。
json_encode における JSON_UNESCAPED_UNICODE に PHP5.3 で対応する - Qiita
おわりに
PHP5.4以上なら普通にJSON_PRETTY_PRINT
が使えるので、素直にそっち使った方が良いです。
あとpreg_replace()
を多用しているので、パフォーマンス的には良くないんでしょう。恐らく。
追記:str_replace()
で普通に出来たので書き換えました。改行コード扱うから、と思い込みがありました。。
とにかく手間が多いので、 レガシーPHPは早く滅びて欲しい。
おまけ
@alt さんから「RaaraでなくLaalaならSofiでなくSophieなのでは」と編集リクエスト頂いたので採用しました。
調べてみたら海外ファンサイトでは「Sophie」なんですね。初めて知りました←