11

My code using json_decode() worked correctly with PHP 5.6. After migration to PHP 7.0, json_decode() returns NULL and json_last_error() tells me that my error is:

Control character error, possibly incorrectly encoded

After debugging, I found out that my problem are both tabs and new line characters in string values. If I remove them both, it works. If I leave either new lines or tabs, the error occurs.

Is json_decode() behavior changed in PHP 7? I would like to keep tabs and new lines in my .json files for better readability. The code works if I replace tabs to \t and new lines to \n.

How can I keep new lines and tabs?

Robo Robok
  • 21,132
  • 17
  • 68
  • 126

4 Answers4

21

Due to a software licensing issue, the old json module was replaced with the jsond module. You can see the discussion of this change and the attached pull request here. Now, there's not much information about the changes or about workarounds for things, but I can see that all control characters inside strings ([\0x00-\0x1F]) trigger an error. Unfortunately for you, it seems that this behavior is correct per the JSON Standard:

Insignificant whitespace is allowed before or after any token. The whitespace characters are: character tabulation (U+0009), line feed (U+000A), carriage return (U+000D), and space (U+0020). Whitespace is not allowed within any token, except that space is allowed in strings.

So, in other words, literal tabs are not allowed inside JSON strings at all; they must be \t or \u0009. So, the JSON you're consuming is in direct violation of the standard. Ideally, you should get your JSON source to return standards-compliant JSON. If that won't work, you'll have to pre-process the JSON and convert tabs inside strings to \t.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Will
  • 24,082
  • 14
  • 97
  • 108
9

I had same problem with new lines and i cant modify the string that i received. I needed to work with it and my trick was to detect the new lines and rewrite it again, 'literaly'!:

Before:

echo json_decode($json); // error JSON_ERROR_CTRL_CHAR

After:

$json = str_replace("\r\n", '\r\n', $json); // single quotes do the trick
echo json_decode($json); // works!
David
  • 131
  • 1
  • 7
4

Tabs and newline characters, unencoded, are not allowed in strings in JSON according to RFC 7159. Therefore, whatever program you used to encode has encoded a non-standard form of JSON. Unfortunately, json_decode's only option, JSON_BIGINT_AS_STRING, doesn't help in this case.

Community
  • 1
  • 1
Peter O.
  • 32,158
  • 14
  • 82
  • 96
  • Do I understand correctly that with PHP 7, they decided to be more strict with JSON standards? If so, it's good in my opinion. Do you think I should sacrifice readability for following JSON standards? And, lastly, any reason why JSON doesn't support new lines and tabs as seen in text editors? – Robo Robok Dec 28 '15 at 00:48
  • @Robo Robok: You can still use tabs and newline characters in a JSON document, but they can't appear in strings themselves without encoding them. – Peter O. Dec 28 '15 at 00:49
  • Yes, they've made it more standards-compliant, and yes, you should absolutely sacrifice the readability in order to use compliant JSON :) – Will Dec 28 '15 at 00:52
  • Thank you for amazing answer. I will choose Will's answer because it contains more details. I hope you don't mind it! :) – Robo Robok Dec 28 '15 at 00:57
0

Maybe this way?

$str = bin2hex('Text with special character /\"\'\b\f\t\r\n.'); // Convert binary data into hexadecimal representation
$arr = array("Some text", "Some text 2", $str);
$Json = json_encode($arr); // Now we are ready to send the json data

Here we will retrieve the json data

$arr_2 = json_decode($Json, true);
echo $arr_2[0];
echo $arr_2[1];
echo hex2bin($arr_2[2]);//Decodes a hexadecimally encoded binary string
adam b
  • 1
  • 1