0

I have this simple JSON string :

{"type_voie":"ALL","indice_repetition":"B","num_voie":"1","nom_voie":"Azrty","infos_voie":"Zzz","distribution_speciale":"","cp":"34230","ville":"PLAISSAN","bureau_distributeur":""}

That I get from my utf8 database.

When I pass it to json_decode($json, true), the result is NULL and json_last_error() give me 4 (JSON_ERROR_SYNTAX)

If I do mb_detect_encoding, I can see that the string is in ASCII, but I only use UTF-8 everywhere.

The string was originally inserted in database from an AJAX query. I got the date from a form serialized with the jQuery function serialize().

I did this a lot in my project and never had problem like this.

I tried to force UTF8 using iconv, mb_convert_encoding or ut8_encode, but nothing change.

I also tried with html_entity_decode() because sometimes PDO is replacing the quotes, but same result.

EDIT :

OH MY GOD. SORRY.

For some reasons, a
was concatenated between the moment I get the json and the moment I send it to the parser. There was just PEBKAC....

I'm so ashamed.

Will delete this post soon

FLX
  • 2,626
  • 4
  • 26
  • 57
  • 1
    There must be a character that you didn't copy. When I paste that string into my script, it works fine. – Barmar Dec 31 '14 at 09:59
  • This is the full string from var_dump() – FLX Dec 31 '14 at 10:01
  • Did you try `json_decode( utf8_encode( $json ) )`? – Sir Rufo Dec 31 '14 at 10:05
  • Yes, and also iconv()... Same result – FLX Dec 31 '14 at 10:06
  • Can you compare the var_dump's reported string length with the string's actual length (by counting the characters on the screen?)? There might be non-printable characters in there. It would explain why copying the string makes it work, because non-printable characters cannot be copied either. – Erik Dec 31 '14 at 10:12
  • @Erik, good idea ! The var_dump() says 184 chars, but in fact i can see 180. Do you know why ? – FLX Dec 31 '14 at 10:15
  • The other 4 characters have no printable representation. As such, they cannot be encoded into JSON either. The best course of action is probably to print all of the string's character-codes in a long list and figure out which invisible characters are in the string, and then either strip them out or find out where they are being inserted and change the code there. – Erik Dec 31 '14 at 10:22

5 Answers5

9

As we found in the comments that there are invisible characters in the string, consider running this bit of code. It should show you each character in the string, it'd ascii value and it's printed version.

There should be a few characters in there which do not print anything; those are the ones preventing you from json_encoding the string. I cannot see why they are in the string, that has something to do with your database and the data you post into it, but at least you'll know where the problem is.

Odds are they are contained inside the inserted data somewhere, which means you probably have a piece of code somewhere that add something unprintable to their input.

You can strip them while exporting, but it would be better to find out which code adds them and remove them from the database. They will continue to bother you in the future otherwise. (As you've seen at this point even something simple like strlen() will fail to work properly due to these characters)

for( $i = 0 ; $i < mb_strlen($string) ; $i++ ) {
  echo 'pos: ' . $i . ' | ord: ' . ord( $string[$i] ) . ' | char: ' . $string[$i] . '<br />';
}
WoodrowShigeru
  • 1,418
  • 1
  • 18
  • 25
Erik
  • 3,598
  • 14
  • 29
  • I accept this answer because you put me in the right way, but it was in fact not only an invisible char but a full HTML tag... – FLX Dec 31 '14 at 10:33
  • Ha. Yeah, those would also be invisible in your browser. Hadn't crossed my mind for a second. Good to hear you have it fixed now! – Erik Dec 31 '14 at 10:36
  • Works great.. Tried every other solution and spent hours debugging it. – Nifal Munzir May 12 '21 at 16:19
  • For people using an API that you can't edit what the API gives you: if you're getting your API result using `file_get_contents`, and it's printing out what _seems_ like a correctly formatted `String`, inspect the string as HTML. It should show you any hidden characters. You can then use the `offset` parameter to trim out those characters. Read more about offset [here](https://www.php.net/manual/en/function.file-get-contents.php). – Ethan Moore Sep 17 '21 at 21:01
8

As guys pointed in previous answers, there can be unprintable characters in json, which means they should be removed before calling json_decode.

One way to do that is this:

$json = preg_replace('/[[:^print:]]/', '', $json);

I am not saying this is the best solution, but so far the only one I found that worked for me.

Alex
  • 1,073
  • 9
  • 20
0

You have to encode your source with UTF-8 before using json_decode()
try with this code :

$json = mb_convert_encoding($json, "UTF-8");
var_dump(json_decode($json, true));
Halayem Anis
  • 7,654
  • 2
  • 25
  • 45
  • Already tried mb_convert_encoding, utf8_encode, iconv... None of these works. I'm beginning to think that it could be a php bug – FLX Dec 31 '14 at 10:09
  • Ok, last chance. first try with mb_convert_encoding($json, "UTF-8", "UTF-8"); (sometimes this function bugs without third argument). else try with : mb_convert_encoding($json, "UTF-8", "ASCII"); also there is a post in sof to convert encoding from ASCII to UTF-8 http://stackoverflow.com/questions/4983989/convert-ascii-to-utf-8-encoding – Halayem Anis Dec 31 '14 at 10:17
0

PHP CURL to API with JSON response

Syntax error, malformed JSON

  • json_last_error() === 4
  • JSON_ERROR_SYNTAX

In my situation, I was using PHP CURL to get JSON data from a local API. I accidentally included HTML in the API's JSON response which caused the error.

After removing the inserted HTML from the API response page, json_decode() executed properly.

Why did this error occur?

CURL requests return the entire page content's as a string. This becomes problematic for json_decode() if content other than JSON is included in the string.

When print/echo'ing a CURL's JSON string on a web page, the string's content can be hidden within the HTML document.

Tip: use var_dump() to compare string lengths to determine if extra content has been included in the JSON string or inspect the page source code to determine if additional code has been included.

MikeySherm
  • 327
  • 4
  • 9
-3

your valid json may be like this add [] in your array then generate json

[{"type_voie":"ALL","indice_repetition":"B","num_voie":"1","nom_voie":"Azrty","infos_voie":"Zzz","distribution_speciale":"","cp":"34230","ville":"PLAISSAN","bureau_distributeur":""}]

Agha Umair Ahmed
  • 1,037
  • 7
  • 12