我正在构建一个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的某个人发现了这一点。
以下是对我有效的方法:
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”标签的使用。
希望这能帮助到别人
递归解的经典例子。这是我的:
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\""
}
}
干杯
我意识到这个问题是问如何编码一个关联数组到一个漂亮的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
}
有颜色全输出:微小的解决方案
代码:
$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。这并不完全是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);
}
}