Как зарегистрировать довольно печатный 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"
  }
}

Как я могу достичь этого результата?

Author: Stephan, 2015-07-13

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() как есть) и беспокоиться о том, чтобы украсить ее только тогда, когда вам нужно прочитать ваши журналы. Это сделает ваши журналы значительно меньше.

 8
Author: TRiG, 2015-07-13 16:36:33

Распространенные журналы ошибок unix не должны содержать удобочитаемый json или другие неэкранированные символы. Многие реализации системного журнала/ведения журнала ограничены шириной символов и автоматически добавляют кодировку (например, \") или удаляют символы новой строки, PHP error_log также небезопасен в двоичном формате - поведение при обнаружении символа юникода непредсказуемо (не уверен).

Вам не следует использовать собственные функции системного журнала/журнала ошибок, вместо этого создайте свой собственный регистратор, посвящен ведению журнала в формате json.

Лично я использую MongoDB для регистрации json, потому что именно с такими данными должен работать MongoDB.

 2
Author: DanFromGermany, 2015-07-13 16:40:29

В этом случае у вас есть два варианта,

Если вы можете использовать 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.

 1
Author: Jean-philippe Emond, 2015-07-13 16:31:36