Pretty-Printing JSON с переполнением стека

Я строю PHP-скрипт, который передает данные JSON в другой скрипт. Мой скрипт строит данные в большой ассоциативный массив, а затем выводит данные, используя json_encode, Вот пример сценария:

$data = array('a' => 'apple', 'b' => 'banana', 'c' => 'catnip');
header('Content-type: text/javascript');
echo json_encode($data);

Приведенный выше код дает следующий вывод:

{"a":"apple","b":"banana","c":"catnip"}

Это замечательно, если у вас небольшой объем данных, но я бы предпочел что-то вроде этого:

{
"a": "apple",
"b": "banana",
"c": "catnip"}

Есть ли способ сделать это в PHP без отвратительного взлома? Кажется, что кто-то в facebook догадаться.

482

Решение

PHP 5.4 предлагает JSON_PRETTY_PRINT вариант для использования с json_encode() вызов.

http://php.net/manual/en/function.json-encode.php

<?php
...
$json_string = json_encode($data, JSON_PRETTY_PRINT);
946

Другие решения

Эта функция будет принимать строку JSON и делать отступ для очень удобного для чтения. Это также должно быть сходящимся,

prettyPrint( $json ) === prettyPrint( prettyPrint( $json ) )

вход

{"key1":[1,2,3],"key2":"value"}

Выход

{
"key1": [
1,
2,
3
],
"key2": "value"}

Код

function prettyPrint( $json )
{
$result = '';
$level = 0;
$in_quotes = false;
$in_escape = false;
$ends_line_level = NULL;
$json_length = strlen( $json );

for( $i = 0; $i < $json_length; $i++ ) {
$char = $json[$i];
$new_line_level = NULL;
$post = "";
if( $ends_line_level !== NULL ) {
$new_line_level = $ends_line_level;
$ends_line_level = NULL;
}
if ( $in_escape ) {
$in_escape = false;
} else if( $char === '"' ) {
$in_quotes = !$in_quotes;
} else if( ! $in_quotes ) {
switch( $char ) {
case '}': case ']':
$level--;
$ends_line_level = NULL;
$new_line_level = $level;
break;

case '{': case '[':
$level++;
case ',':
$ends_line_level = $level;
break;

case ':':
$post = " ";
break;

case " ": case "\t": case "\n": case "\r":
$char = "";
$ends_line_level = $new_line_level;
$new_line_level = NULL;
break;
}
} else if ( $char === '\\' ) {
$in_escape = true;
}
if( $new_line_level !== NULL ) {
$result .= "\n".str_repeat( "\t", $new_line_level );
}
$result .= $char.$post;
}

return $result;
}
179

Многие пользователи предложили вам использовать

echo json_encode($results, JSON_PRETTY_PRINT);

Что абсолютно верно. Но этого недостаточно, браузер должен понимать тип данных, вы можете указать заголовок непосредственно перед отправкой данных пользователю.

header('Content-Type: application/json');

Это приведет к хорошо отформатированному выводу.

Или, если вам нравятся расширения, вы можете использовать JSONView для Chrome.

56

Я была такая же проблема.

В любом случае, я просто использовал код форматирования json:

http://recursive-design.com/blog/2008/03/11/format-json-with-php/

Хорошо работает для того, что мне нужно.

И более поддерживаемая версия: https://github.com/GerHobbelt/nicejson-php

40

Я понимаю, что этот вопрос задает вопрос о том, как кодировать ассоциативный массив в довольно отформатированную строку JSON, так что это не дает прямого ответа на вопрос, но если у вас есть строка, которая уже находится в формате JSON, вы можете сделать ее довольно просто путем декодирования и перекодирования (требуется PHP> = 5.4):

$json = json_encode(json_decode($json), JSON_PRETTY_PRINT);

Пример:

header('Content-Type: application/json');
$json_ugly = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
$json_pretty = json_encode(json_decode($json_ugly), JSON_PRETTY_PRINT);
echo $json_pretty;

Это выводит:

{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5
}
18

Если вы используете Firefox, установите JSONovich. Я знаю, что это не совсем PHP-решение, но оно подходит для целей разработки / отладки.

10

Я взял код от Composer: https://github.com/composer/composer/blob/master/src/Composer/Json/JsonFile.php и nicejson: https://github.com/GerHobbelt/nicejson-php/blob/master/nicejson.php
Код Composer хорош, потому что он свободно обновляется с 5.3 до 5.4, но кодирует только объект, тогда как nicejson принимает строки json, поэтому я объединил их. Код можно использовать для форматирования строки json и / или кодирования объектов, в настоящее время я использую его в модуле Drupal.

if (!defined('JSON_UNESCAPED_SLASHES'))
define('JSON_UNESCAPED_SLASHES', 64);
if (!defined('JSON_PRETTY_PRINT'))
define('JSON_PRETTY_PRINT', 128);
if (!defined('JSON_UNESCAPED_UNICODE'))
define('JSON_UNESCAPED_UNICODE', 256);

function _json_encode($data, $options = 448)
{
if (version_compare(PHP_VERSION, '5.4', '>='))
{
return json_encode($data, $options);
}

return _json_format(json_encode($data), $options);
}

function _pretty_print_json($json)
{
return _json_format($json, JSON_PRETTY_PRINT);
}

function _json_format($json, $options = 448)
{
$prettyPrint = (bool) ($options & JSON_PRETTY_PRINT);
$unescapeUnicode = (bool) ($options & JSON_UNESCAPED_UNICODE);
$unescapeSlashes = (bool) ($options & JSON_UNESCAPED_SLASHES);

if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes)
{
return $json;
}

$result = '';
$pos = 0;
$strLen = strlen($json);
$indentStr = ' ';
$newLine = "\n";
$outOfQuotes = true;
$buffer = '';
$noescape = true;

for ($i = 0; $i < $strLen; $i++)
{
// Grab the next character in the string
$char = substr($json, $i, 1);

// Are we inside a quoted string?
if ('"' === $char && $noescape)
{
$outOfQuotes = !$outOfQuotes;
}

if (!$outOfQuotes)
{
$buffer .= $char;
$noescape = '\\' === $char ? !$noescape : true;
continue;
}
elseif ('' !== $buffer)
{
if ($unescapeSlashes)
{
$buffer = str_replace('\\/', '/', $buffer);
}

if ($unescapeUnicode && function_exists('mb_convert_encoding'))
{
// http://stackoverflow.com/questions/2934563/how-to-decode-unicode-escape-sequences-like-u00ed-to-proper-utf-8-encoded-cha
$buffer = preg_replace_callback('/\\\\u([0-9a-f]{4})/i',
function ($match)
{
return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE');
}, $buffer);
}

$result .= $buffer . $char;
$buffer = '';
continue;
}
elseif(false !== strpos(" \t\r\n", $char))
{
continue;
}

if (':' === $char)
{
// Add a space after the : character
$char .= ' ';
}
elseif (('}' === $char || ']' === $char))
{
$pos--;
$prevChar = substr($json, $i - 1, 1);

if ('{' !== $prevChar && '[' !== $prevChar)
{
// If this character is the end of an element,
// output a new line and indent the next line
$result .= $newLine;
for ($j = 0; $j < $pos; $j++)
{
$result .= $indentStr;
}
}
else
{
// Collapse empty {} and []
$result = rtrim($result) . "\n\n" . $indentStr;
}
}

$result .= $char;

// If the last character was the beginning of an element,
// output a new line and indent the next line
if (',' === $char || '{' === $char || '[' === $char)
{
$result .= $newLine;

if ('{' === $char || '[' === $char)
{
$pos++;
}

for ($j = 0; $j < $pos; $j++)
{
$result .= $indentStr;
}
}
}
// If buffer not empty after formating we have an unclosed quote
if (strlen($buffer) > 0)
{
//json is incorrectly formatted
$result = false;
}

return $result;
}
10

Простой способ для php> 5.4: как в графике Facebook

$Data = array('a' => 'apple', 'b' => 'banana', 'c' => 'catnip');
$json= json_encode($Data, JSON_PRETTY_PRINT);
header('Content-Type: application/json');
print_r($json);

Результат в браузере

{
"a": "apple",
"b": "banana",
"c": "catnip"}
6
По вопросам рекламы [email protected]