[英]Pretty-Printing JSON with PHP
我正在構建一個 PHP 腳本,它將 JSON 數據提供給另一個腳本。 我的腳本將數據構建到一個大型關聯數組中,然后使用json_encode
輸出數據。 這是一個示例腳本:
$data = array('a' => 'apple', 'b' => 'banana', 'c' => 'catnip');
header('Content-type: text/javascript');
echo json_encode($data);
上面的代碼產生以下 output:
{"a":"apple","b":"banana","c":"catnip"}
如果您有少量數據,這很好,但我更喜歡這些方面的內容:
{
"a": "apple",
"b": "banana",
"c": "catnip"
}
有沒有辦法在 PHP 中做到這一點而沒有丑陋的黑客攻擊? 似乎Facebook的某個人弄明白了。
PHP 5.4 提供了
JSON_PRETTY_PRINT<\/code>選項以用於
json_encode()<\/code>調用。
http:\/\/php.net\/manual\/en\/function.json-encode.php<\/a>
<?php
...
$json_string = json_encode($data, JSON_PRETTY_PRINT);
此函數將采用 JSON 字符串並將其縮進非常易讀。 它也應該是收斂的,
prettyPrint( $json ) === prettyPrint( prettyPrint( $json ) )
許多用戶建議您使用
echo json_encode($results, JSON_PRETTY_PRINT);
這是絕對正確的。 但這還不夠,瀏覽器需要了解數據的類型,您可以在將數據回顯給用戶之前指定標題。
header('Content-Type: application/json');
這將產生格式良好的輸出。
或者,如果你喜歡擴展,你可以使用 JSONView for Chrome。
我意識到這個問題是在詢問如何將關聯數組編碼為格式精美的 JSON 字符串,因此這並不能直接回答問題,但是如果您有一個已經是 JSON 格式的字符串,則可以非常簡單通過解碼和重新編碼(需要 PHP >= 5.4):
$json = json_encode(json_decode($json), JSON_PRETTY_PRINT);
我遇到過同樣的問題。
無論如何,我只是在這里使用了 json 格式化代碼:
http:\/\/recursive-design.com\/blog\/2008\/03\/11\/format-json-with-php\/<\/a>
很適合我需要的東西。
還有一個更維護的版本: https<\/a> :\/\/github.com\/GerHobbelt\/nicejson-php
將幾個答案粘合在一起符合我對現有 json 的需求:
Code:
echo "<pre>";
echo json_encode(json_decode($json_response), JSON_PRETTY_PRINT);
echo "</pre>";
Output:
{
"data": {
"token_type": "bearer",
"expires_in": 3628799,
"scopes": "full_access",
"created_at": 1540504324
},
"errors": [],
"pagination": {},
"token_type": "bearer",
"expires_in": 3628799,
"scopes": "full_access",
"created_at": 1540504324
}
我用過這個:
echo "<pre>".json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)."</pre>";
我從 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;
}
彩色全輸出:Tiny Solution
代碼:
$s = '{"access": {"token": {"issued_at": "2008-08-16T14:10:31.309353", "expires": "2008-08-17T14:10:31Z", "id": "MIICQgYJKoZIhvcIegeyJpc3N1ZWRfYXQiOiAi"}, "serviceCatalog": [], "user": {"username": "ajay", "roles_links": [], "id": "16452ca89", "roles": [], "name": "ajay"}}}';
$crl = 0;
$ss = false;
echo "<pre>";
for($c=0; $c<strlen($s); $c++)
{
if ( $s[$c] == '}' || $s[$c] == ']' )
{
$crl--;
echo "\n";
echo str_repeat(' ', ($crl*2));
}
if ( $s[$c] == '"' && ($s[$c-1] == ',' || $s[$c-2] == ',') )
{
echo "\n";
echo str_repeat(' ', ($crl*2));
}
if ( $s[$c] == '"' && !$ss )
{
if ( $s[$c-1] == ':' || $s[$c-2] == ':' )
echo '<span style="color:#0000ff;">';
else
echo '<span style="color:#ff0000;">';
}
echo $s[$c];
if ( $s[$c] == '"' && $ss )
echo '</span>';
if ( $s[$c] == '"' )
$ss = !$ss;
if ( $s[$c] == '{' || $s[$c] == '[' )
{
$crl++;
echo "\n";
echo str_repeat(' ', ($crl*2));
}
}
echo $s[$c];
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"
}
格式化 JSON 數據的最佳方式是這樣的!
header('Content-type: application/json; charset=UTF-8');
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
更簡單,輸入 128 - 是“JSON_PRETTY_PRINT”的同義詞
json_encode($json,128);
//OR same
json_encode($json,JSON_PRETTY_PRINT );
將
<pre><\/code>與
json_encode()<\/code>和
JSON_PRETTY_PRINT<\/code>選項結合使用:
<pre>
<?php
echo json_encode($dataArray, JSON_PRETTY_PRINT);
?>
</pre>
如果您有現有的 JSON ( $ugly_json
)
echo nl2br(str_replace(' ', ' ', (json_encode(json_decode($ugly_json), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES))));
您可以在 switch 語句中稍微修改 Kendall Hopkins 的答案,通過將 json 字符串傳遞到以下內容來獲得看起來非常干凈且縮進良好的打印輸出:
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;
$char.="<br>";
for($index=0;$index<$level-1;$index++){$char.="-----";}
break;
case '{': case '[':
$level++;
$char.="<br>";
for($index=0;$index<$level;$index++){$char.="-----";}
break;
case ',':
$ends_line_level = $level;
$char.="<br>";
for($index=0;$index<$level;$index++){$char.="-----";}
break;
case ':':
$post = " ";
break;
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;
}
echo "RESULTS ARE: <br><br>$result";
return $result;
對於那些運行 PHP 5.3 或之前版本的用戶,您可以嘗試以下操作:
$pretty_json = "<pre>".print_r(json_decode($json), true)."</pre>";
echo $pretty_json;
如果你只使用$json_string = json_encode($data, JSON_PRETTY_PRINT);
,您將在瀏覽器中看到類似這樣的內容(使用問題中的Facebook 鏈接:)):
但是如果你使用像JSONView這樣的 chrome 擴展(即使沒有上面的 PHP 選項),那么你會得到一個更易讀的可調試解決方案,你甚至可以像這樣輕松地折疊/折疊每個 JSON 對象:
你可以像下面那樣做。
$array = array(
"a" => "apple",
"b" => "banana",
"c" => "catnip"
);
foreach ($array as $a_key => $a_val) {
$json .= "\"{$a_key}\" : \"{$a_val}\",\n";
}
header('Content-Type: application/json');
echo "{\n" .rtrim($json, ",\n") . "\n}";
上面會輸出有點像 Facebook。
{
"a" : "apple",
"b" : "banana",
"c" : "catnip"
}
遞歸解決方案的經典案例。 這是我的:
class JsonFormatter {
public static function prettyPrint(&$j, $indentor = "\t", $indent = "") {
$inString = $escaped = false;
$result = $indent;
if(is_string($j)) {
$bak = $j;
$j = str_split(trim($j, '"'));
}
while(count($j)) {
$c = array_shift($j);
if(false !== strpos("{[,]}", $c)) {
if($inString) {
$result .= $c;
} else if($c == '{' || $c == '[') {
$result .= $c."\n";
$result .= self::prettyPrint($j, $indentor, $indentor.$indent);
$result .= $indent.array_shift($j);
} else if($c == '}' || $c == ']') {
array_unshift($j, $c);
$result .= "\n";
return $result;
} else {
$result .= $c."\n".$indent;
}
} else {
$result .= $c;
$c == '"' && !$escaped && $inString = !$inString;
$escaped = $c == '\\' ? !$escaped : false;
}
}
$j = $bak;
return $result;
}
}
這個解決方案使 JSON 變得“非常漂亮”。 不完全是 OP 所要求的,但它可以讓您更好地可視化 JSON。
/**
* takes an object parameter and returns the pretty json format.
* this is a space saving version that uses 2 spaces instead of the regular 4
*
* @param $in
*
* @return string
*/
function pretty_json ($in): string
{
return preg_replace_callback('/^ +/m',
function (array $matches): string
{
return str_repeat(' ', strlen($matches[0]) / 2);
}, json_encode($in, JSON_PRETTY_PRINT | JSON_HEX_APOS)
);
}
/**
* takes a JSON string an adds colours to the keys/values
* if the string is not JSON then it is returned unaltered.
*
* @param string $in
*
* @return string
*/
function markup_json (string $in): string
{
$string = 'green';
$number = 'darkorange';
$null = 'magenta';
$key = 'red';
$pattern = '/("(\\\\u[a-zA-Z0-9]{4}|\\\\[^u]|[^\\\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/';
return preg_replace_callback($pattern,
function (array $matches) use ($string, $number, $null, $key): string
{
$match = $matches[0];
$colour = $number;
if (preg_match('/^"/', $match))
{
$colour = preg_match('/:$/', $match)
? $key
: $string;
}
elseif ($match === 'null')
{
$colour = $null;
}
return "<span style='color:{$colour}'>{$match}</span>";
}, str_replace(['<', '>', '&'], ['<', '>', '&'], $in)
) ?? $in;
}
public function test_pretty_json_object ()
{
$ob = new \stdClass();
$ob->test = 'unit-tester';
$json = pretty_json($ob);
$expected = <<<JSON
{
"test": "unit-tester"
}
JSON;
$this->assertEquals($expected, $json);
}
public function test_pretty_json_str ()
{
$ob = 'unit-tester';
$json = pretty_json($ob);
$this->assertEquals("\"$ob\"", $json);
}
public function test_markup_json ()
{
$json = <<<JSON
[{"name":"abc","id":123,"warnings":[],"errors":null},{"name":"abc"}]
JSON;
$expected = <<<STR
[
{
<span style='color:red'>"name":</span> <span style='color:green'>"abc"</span>,
<span style='color:red'>"id":</span> <span style='color:darkorange'>123</span>,
<span style='color:red'>"warnings":</span> [],
<span style='color:red'>"errors":</span> <span style='color:magenta'>null</span>
},
{
<span style='color:red'>"name":</span> <span style='color:green'>"abc"</span>
}
]
STR;
$output = markup_json(pretty_json(json_decode($json)));
$this->assertEquals($expected,$output);
}
}
用於 PHP 的 print_r 漂亮打印
function print_nice($elem,$max_level=10,$print_nice_stack=array()){
if(is_array($elem) || is_object($elem)){
if(in_array($elem,$print_nice_stack,true)){
echo "<font color=red>RECURSION</font>";
return;
}
$print_nice_stack[]=&$elem;
if($max_level<1){
echo "<font color=red>nivel maximo alcanzado</font>";
return;
}
$max_level--;
echo "<table border=1 cellspacing=0 cellpadding=3 width=100%>";
if(is_array($elem)){
echo '<tr><td colspan=2 style="background-color:#333333;"><strong><font color=white>ARRAY</font></strong></td></tr>';
}else{
echo '<tr><td colspan=2 style="background-color:#333333;"><strong>';
echo '<font color=white>OBJECT Type: '.get_class($elem).'</font></strong></td></tr>';
}
$color=0;
foreach($elem as $k => $v){
if($max_level%2){
$rgb=($color++%2)?"#888888":"#BBBBBB";
}else{
$rgb=($color++%2)?"#8888BB":"#BBBBFF";
}
echo '<tr><td valign="top" style="width:40px;background-color:'.$rgb.';">';
echo '<strong>'.$k."</strong></td><td>";
print_nice($v,$max_level,$print_nice_stack);
echo "</td></tr>";
}
echo "</table>";
return;
}
if($elem === null){
echo "<font color=green>NULL</font>";
}elseif($elem === 0){
echo "0";
}elseif($elem === true){
echo "<font color=green>TRUE</font>";
}elseif($elem === false){
echo "<font color=green>FALSE</font>";
}elseif($elem === ""){
echo "<font color=green>EMPTY STRING</font>";
}else{
echo str_replace("\n","<strong><font color=red>*</font></strong><br>\n",$elem);
}
}
1 -
json_encode($rows,JSON_PRETTY_PRINT);<\/code>
返回帶有換行符的美化數據。 這對命令行輸入很有幫助,但正如您所發現的那樣,在瀏覽器中看起來並不那么漂亮。 瀏覽器將接受換行符作為源(因此,查看頁面源確實會顯示漂亮的 JSON),但它們不用於格式化瀏覽器中的輸出。 瀏覽器需要 HTML。
<?php
/**
* Formats a JSON string for pretty printing
*
* @param string $json The JSON to make pretty
* @param bool $html Insert nonbreaking spaces and <br />s for tabs and linebreaks
* @return string The prettified output
* @author Jay Roberts
*/
function _format_json($json, $html = false) {
$tabcount = 0;
$result = '';
$inquote = false;
$ignorenext = false;
if ($html) {
$tab = " ";
$newline = "<br/>";
} else {
$tab = "\t";
$newline = "\n";
}
for($i = 0; $i < strlen($json); $i++) {
$char = $json[$i];
if ($ignorenext) {
$result .= $char;
$ignorenext = false;
} else {
switch($char) {
case '[':
case '{':
$tabcount++;
$result .= $char . $newline . str_repeat($tab, $tabcount);
break;
case ']':
case '}':
$tabcount--;
$result = trim($result) . $newline . str_repeat($tab, $tabcount) . $char;
break;
case ',':
$result .= $char . $newline . str_repeat($tab, $tabcount);
break;
case '"':
$inquote = !$inquote;
$result .= $char;
break;
case '\\':
if ($inquote) $ignorenext = true;
$result .= $char;
break;
default:
$result .= $char;
}
}
}
return $result;
}
這是我自己使用的函數,api 就像 json_encode,除了它有第三個參數exclude_flags
以防你想排除一些默認標志(如 JSON_UNESCAPED_SLASHES)
function json_encode_pretty($data, int $extra_flags = 0, int $exclude_flags = 0): string
{
// prettiest flags for: 7.3.9
$flags = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | (defined("JSON_UNESCAPED_LINE_TERMINATORS") ? JSON_UNESCAPED_LINE_TERMINATORS : 0) | JSON_PRESERVE_ZERO_FRACTION | (defined("JSON_THROW_ON_ERROR") ? JSON_THROW_ON_ERROR : 0);
$flags = ($flags | $extra_flags) & ~ $exclude_flags;
return (json_encode($data, $flags));
}
我通常使用這些單線之一。
如果您已經有一個 JSON 字符串,您可以簡單地使用echo()
和print_r()
的組合。 不要忘記將print_r()
的第二個參數傳遞給true
以便它返回值而不是打印它:
echo('<pre>' . print_r($json, true) . '</pre>');
或者您可以使用方便調試的die()
:
die('<pre>' . print_r($json, true) . '</pre>');
如果你有一個數組,你需要先把它轉換成一個JSON的字符串。 請務必使用JSON_PRETTY_PRINT
標志設置json_encode()
的第二個參數,以便正確呈現您的 JSON:
echo('<pre>' . print_r(json_encode($array, JSON_PRETTY_PRINT), true) . '</pre>');
或用於調試:
die('<pre>' . print_r(json_encode($array, JSON_PRETTY_PRINT), true) . '</pre>');
以下是對我有用的:
test.php 的內容:
<html>
<body>
Testing JSON array output
<pre>
<?php
$data = array('a'=>'apple', 'b'=>'banana', 'c'=>'catnip');
// encode in json format
$data = json_encode($data);
// json as single line
echo "</br>Json as single line </br>";
echo $data;
// json as an array, formatted nicely
echo "</br>Json as multiline array </br>";
print_r(json_decode($data, true));
?>
</pre>
</body>
</html>
如果您正在使用MVC<\/strong>
嘗試在您的控制器中執行此操作
public function getLatestUsers() {
header('Content-Type: application/json');
echo $this->model->getLatestUsers(); // this returns json_encode($somedata, JSON_PRETTY_PRINT)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.