漂亮的打印与PHP的JSON

我正在构build一个将JSON数据提供给另一个脚本的PHP脚本。 我的脚本将数据构build成一个大的关联数组,然后使用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"} 

如果你有less量的数据,这是非常好的,但我更喜欢这些方面的东西:

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

有没有办法做到这一点在PHP中没有丑陋的黑客? Facebook上的某个人似乎已经明白了。

PHP 5.4提供了与json_encode()调用一起使用的JSON_PRETTY_PRINT选项。

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

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

这个函数将采取JSONstring并缩进它非常可读。 它也应该收敛,

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

input

 {"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; } 

我遇到过同样的问题。

无论如何,我只是在这里使用json格式的代码:

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

适合我需要的东西。

而更维护的版本: https : //github.com/GerHobbelt/nicejson-php

许多用户build议您使用

 echo json_encode($results, JSON_PRETTY_PRINT); 

这是绝对正确的。 但这还不够,浏览器需要了解数据的types,您可以在将数据回送给用户之前指定标题。

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

这将产生格式良好的输出。

或者,如果您喜欢扩展,则可以使用JSONView for Chrome。

如果你是在Firefox上安装JSONovich 。 不是我知道的一个PHP解决scheme,但它为开发目的/debugging提供了技巧。

我从composer php的代码: https : //github.com/composer/composer/blob/master/src/Composer/Json/JsonFile.php和nicejson: https : //github.com/GerHobbelt/nicejson-php/blob /master/nicejson.php编写器代码是好的,因为它从5.3更新到5.4,但它只编码对象,而nicejson接受JSONstring,所以我合并它们。 该代码可以用来格式化jsonstring和/或编码对象,我目前正在使用它在一个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; } 

我意识到这个问题是关于如何将一个关联数组编码为一个相当格式的JSONstring,所以这并不直接回答这个问题,但是如果你有一个已经是JSON格式的string,你可以简单的通过解码和重新编码(需要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 } 

结合使用<pre>json_encode()以及JSON_PRETTY_PRINT选项:

 <pre> <?php echo json_encode($dataArray, JSON_PRETTY_PRINT); ?> </pre> 

你可以在switch语句中修改一下Kendall Hopkins的答案,通过传递一个jsonstring来得到一个相当干净的,很好的缩进输出:

 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; 

}

现在只需运行函数prettyPrint($ your_json_string); 内联在您的PHP和享受打印输出。 如果你是一个极简主义者,并且由于某种原因不喜欢括号,你可以通过replace$char.="<br>";$char="<br>"; 在$ char的前三个开关情况下。 以下是您获得卡尔加里市Google Maps API调用所需的信息

 RESULTS ARE: { - - - "results" : [ - - -- - - { - - -- - -- - - "address_components" : [ - - -- - -- - -- - - { - - -- - -- - -- - -- - - "long_name" : "Calgary" - - -- - -- - -- - -- - - "short_name" : "Calgary" - - -- - -- - -- - -- - - "types" : [ - - -- - -- - -- - -- - -- - - "locality" - - -- - -- - -- - -- - -- - - "political" ] - - -- - -- - -- - - } - - -- - -- - - - - -- - -- - -- - - { - - -- - -- - -- - -- - - "long_name" : "Division No. 6" - - -- - -- - -- - -- - - "short_name" : "Division No. 6" - - -- - -- - -- - -- - - "types" : [ - - -- - -- - -- - -- - -- - - "administrative_area_level_2" - - -- - -- - -- - -- - -- - - "political" ] - - -- - -- - -- - - } - - -- - -- - - - - -- - -- - -- - - { - - -- - -- - -- - -- - - "long_name" : "Alberta" - - -- - -- - -- - -- - - "short_name" : "AB" - - -- - -- - -- - -- - - "types" : [ - - -- - -- - -- - -- - -- - - "administrative_area_level_1" - - -- - -- - -- - -- - -- - - "political" ] - - -- - -- - -- - - } - - -- - -- - - - - -- - -- - -- - - { - - -- - -- - -- - -- - - "long_name" : "Canada" - - -- - -- - -- - -- - - "short_name" : "CA" - - -- - -- - -- - -- - - "types" : [ - - -- - -- - -- - -- - -- - - "country" - - -- - -- - -- - -- - -- - - "political" ] - - -- - -- - -- - - } - - -- - -- - - ] - - -- - - - - -- - -- - - "formatted_address" : "Calgary, AB, Canada" - - -- - -- - - "geometry" : { - - -- - -- - -- - - "bounds" : { - - -- - -- - -- - -- - - "northeast" : { - - -- - -- - -- - -- - -- - - "lat" : 51.18383 - - -- - -- - -- - -- - -- - - "lng" : -113.8769511 } - - -- - -- - -- - - - - -- - -- - -- - -- - - "southwest" : { - - -- - -- - -- - -- - -- - - "lat" : 50.84240399999999 - - -- - -- - -- - -- - -- - - "lng" : -114.27136 } - - -- - -- - -- - - } - - -- - -- - - - - -- - -- - -- - - "location" : { - - -- - -- - -- - -- - - "lat" : 51.0486151 - - -- - -- - -- - -- - - "lng" : -114.0708459 } - - -- - -- - - - - -- - -- - -- - - "location_type" : "APPROXIMATE" - - -- - -- - -- - - "viewport" : { - - -- - -- - -- - -- - - "northeast" : { - - -- - -- - -- - -- - -- - - "lat" : 51.18383 - - -- - -- - -- - -- - -- - - "lng" : -113.8769511 } - - -- - -- - -- - - - - -- - -- - -- - -- - - "southwest" : { - - -- - -- - -- - -- - -- - - "lat" : 50.84240399999999 - - -- - -- - -- - -- - -- - - "lng" : -114.27136 } - - -- - -- - -- - - } - - -- - -- - - } - - -- - - - - -- - -- - - "place_id" : "ChIJ1T-EnwNwcVMROrZStrE7bSY" - - -- - -- - - "types" : [ - - -- - -- - -- - - "locality" - - -- - -- - -- - - "political" ] - - -- - - } - - - ] - - - "status" : "OK" } 

有颜色完整的输出:微小的解决scheme

码:

 $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]; 

如果您只使用$json_string = json_encode($data, JSON_PRETTY_PRINT); ,你会得到像这样的浏览器(使用从问题的Facebook链接 :)): 在这里输入图像描述

但是如果你使用了像JSONView这样的Chrome扩展(甚至没有上面的PHP选项),那么你会得到一个更可读的可debugging解决scheme ,你甚至可以像这样简单地折叠/折叠每个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" } 

简单的方法为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 $ ugly_json:

 echo nl2br(str_replace(' ', '&nbsp;', (json_encode(json_decode($ugly_json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)))); 

经典案例的recursion解决scheme。 这是我的:

 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; } } 

用法:

 php > require 'JsonFormatter.php'; php > $a = array('foo' => 1, 'bar' => 'This "is" bar', 'baz' => array('a' => 1, 'b' => 2, 'c' => '"3"')); php > print_r($a); Array ( [foo] => 1 [bar] => This "is" bar [baz] => Array ( [a] => 1 [b] => 2 [c] => "3" ) ) php > echo JsonFormatter::prettyPrint(json_encode($a)); { "foo":1, "bar":"This \"is\" bar", "baz":{ "a":1, "b":2, "c":"\"3\"" } } 

干杯

print_r漂亮的PHP打印

示例PHP

 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); 用换行符返回美化的数据。 这对命令行input很有帮助,但正如你发现在浏览器中看起来不那么漂亮。 浏览器将接受换行符作为源代码(因此,查看页面源代码确实会显示漂亮的JSON),但是它们不用于在浏览器中格式化输出。 浏览器需要HTML。

2 – 使用这个functiongithub

 <?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 = "&nbsp;&nbsp;&nbsp;"; $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 '{': $tabcount++; $result .= $char . $newline . str_repeat($tab, $tabcount); break; 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; } 

以下是为我工作的:

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> 

输出:

 Testing JSON array output Json as single line {"a":"apple","b":"banana","c":"catnip"} Json as multiline array Array ( [a] => apple [b] => banana [c] => catnip ) 

还要注意在html中使用“pre”标签。

希望能帮助别人

如果你正在使用MVC

尝试在你的控制器做这个

 public function getLatestUsers() { header('Content-Type: application/json'); echo $this->model->getLatestUsers(); // this returns json_encode($somedata, JSON_PRETTY_PRINT) } 

那么如果你调用/ getLatestUsers,你会得到一个漂亮的JSON输出;)

我没有足够的信誉来回复肯德尔·霍普金斯,但是我发现他的美化者有一个缺陷(它也很笨拙地出现)

这行应该修改:

 if( $char === '"' && $prev_char != '\\' ) { 

 if( $char === '"' && ($prev_char != '\\' && $prev_prev_char != '\\' ) { 

当一个string以反斜杠结尾时,prettifier会中断并生成无效的json:

 "kittens\\"