Как зарегистрировать довольно печатный json в PHP?
Я создаю API на php. Этот API обрабатывает сообщения json от стороннего API.
Я хочу регистрировать недопустимые довольно печатные сообщения 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"
}
}
Как я могу достичь этого результата?
3 answers
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 тоже будет рассматривать как строку.
Сообразительный?
Итак, что вам нужно сделать, это (а) превратить $json_string
обратно в массив PHP, а затем (б) повторно закодировать его как 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);
Вместо того, чтобы преобразовывать его обратно в массив PHP и затем, возвращаясь к JSON, было бы лучше добавить флаг JSON_PRETTY_PRINT
туда, откуда вы получаете $json_string
в первую очередь, если это возможно.
В качестве альтернативы, просто регистрируйте $json_string
напрямую (не нужно кодировать его: это уже строка, вы можете передать ее в error_log()
как есть) и беспокоиться о том, чтобы украсить ее только тогда, когда вам нужно прочитать ваши журналы. Это сделает ваши журналы значительно меньше.
Распространенные журналы ошибок unix не должны содержать удобочитаемый json или другие неэкранированные символы. Многие реализации системного журнала/ведения журнала ограничены шириной символов и автоматически добавляют кодировку (например, \"
) или удаляют символы новой строки, PHP error_log также небезопасен в двоичном формате - поведение при обнаружении символа юникода непредсказуемо (не уверен).
Вам не следует использовать собственные функции системного журнала/журнала ошибок, вместо этого создайте свой собственный регистратор, посвящен ведению журнала в формате json.
Лично я использую MongoDB для регистрации json, потому что именно с такими данными должен работать MongoDB.
В этом случае у вас есть два варианта,
Если вы можете использовать str_replace, например:
error_log("test\n" . str_replace('\"',"\n",json_encode($json_string, JSON_PRETTY_PRINT)));
Или, как сказал @Кароли Хорват:
Вы кодируете строку, уже закодированную в JSON. Ваша строка $json_string уже закодирована. Поэтому вам нужно декодировать свой первый JSON и перекодировать его с хорошими параметрами
error_log("test\n" . json_encode(json_decode($json_string), JSON_PRETTY_PRINT));
И отдайте должное @Karoly.