我在php中构建API。此API处理来自第三方API的json消息。
我想记录无效的漂亮打印的json消息。
所以我这样做了:
error_log("test\n" . json_encode($json_string, JSON_PRETTY_PRINT));
但是,当我查看我的日志时,json字符串打印效果不是很好:
$ tailf error.log
2015-07-13 10:20:03: (mod_fastcgi.c.2701) FastCGI-stderr: test
"{\"info\":{\"status\":200,\"msg\":\"OK\"},\"response\":{\"foo\":\"bar\"}"
我希望看到类似的内容:
$ tailf error.log
2015-07-13 10:20:03: (mod_fastcgi.c.2701) FastCGI-stderr: test
{
"info": {
"status": 200,
"msg ": "OK"
},
"response": {
"foo": "bar"
}
}
我怎样才能获得这个结果?
答案 0 :(得分:12)
error_log("test\n" . json_encode($json_string, JSON_PRETTY_PRINT));
json_encode()
实际上不一定会生成JSON:它会生成一些可以通过javascript读取的东西。如果你给它一个数组或一个对象,它将产生JSON;如果你给它一个字符串,它将产生一个javascript字符串。这就是你正在做的事情,所以这就是你所得到的。
要清楚,$json_string
是字符串 :(就PHP而言,它是一个字符串;如果您将相同的字符串传递给javascript,它将被解释为宾语)。你通过json_encode()
传递了它,你要获得的是另一个字符串(一串双重编码的JSON)。
JSON_PRETTY_PRINT
在这里没有任何效果,因为你没有生成JSON:你正在制作一些javascript也会看作字符串的东西。
精明?
所以你需要做的是(a)将$json_string
转回PHP数组,然后(b)将其重新编码为JSON,这次使用JSON_PRETTY_PRINT
标志。
$log_array = json_decode($json_string, true);
$json_pretty_string = json_encode($log_array, JSON_PRETTY_PRINT);
error_log('test' . PHP_EOL . $json_pretty_string);
如果可能的话,最好将JSON_PRETTY_PRINT
标志添加到您首先获得$json_string
的位置,而不是将其转换回PHP数组然后再返回到JSON。
或者,只需直接记录$json_string
(无需对其进行编码:它已经是一个字符串,您可以将其原样传递给error_log()
),并担心只在您需要时才对其进行美化读取您的日志。这将使您的日志变得更小。
答案 1 :(得分:1)
常见的unix错误日志不应包含人类可读的json或其他未转义的字符。许多系统日志/日志记录实现受字符宽度限制并自动添加编码(如\"
)或删除新行字符,PHP的error_log也不是二进制安全 - 遇到unicode字符时的行为是不可预测的(不确定)
您不应该使用本机syslog /错误日志功能,而是 建立自己的记录器,专门用于json日志记录。
我个人使用MongoDB来记录json,因为它是MongoDB应该使用的那种数据。
答案 2 :(得分:0)
在这种情况下,您有两种选择,
如果你可以使用str_replace,如:
error_log("test\n" . str_replace('\"',"\n",json_encode($json_string, JSON_PRETTY_PRINT)));
或者像@Karoly Horvath说的那样:
您编码已在JSON中编码的字符串。您的$ json_string已经编码。所以你需要解码你的第一个JSON并用好参数重新编码
error_log("test\n" . json_encode(json_decode($json_string), JSON_PRETTY_PRINT));
并赞扬@Karoly。