PHP json_decode () renvoie NULL avec un JSON valide?

104

J'ai cet objet JSON stocké dans un fichier texte brut:

{
    "MySQL": {
        "Server": "(server)",
        "Username": "(user)",
        "Password": "(pwd)",
        "DatabaseName": "(dbname)"
    },
    "Ftp": {
        "Server": "(server)",
        "Username": "(user)",
        "Password": "(pwd)",
        "RootFolder": "(rf)"
    },
    "BasePath": "../../bin/",
    "NotesAppPath": "notas",
    "SearchAppPath": "buscar",
    "BaseUrl": "http:\/\/montemaiztusitio.com.ar",
    "InitialExtensions": [
        "nem.mysqlhandler",
        "nem.string",
        "nem.colour",
        "nem.filesystem",
        "nem.rss",
        "nem.date",
        "nem.template",
        "nem.media",
        "nem.measuring",
        "nem.weather",
        "nem.currency"
    ],
    "MediaPath": "media",
    "MediaGalleriesTable": "journal_media_galleries",
    "MediaTable": "journal_media",
    "Journal": {
        "AllowedAdFileFormats": [
            "flv:1",
            "jpg:2",
            "gif:3",
            "png:4",
            "swf:5"
        ],
        "AdColumnId": "3",
        "RSSLinkFormat": "%DOMAIN%\/notas\/%YEAR%-%MONTH%-%DAY%\/%TITLE%/",
        "FrontendLayout": "Flat",
        "AdPath": "ad",
        "SiteTitle": "Monte Maíz: Tu Sitio",
        "GlobalSiteDescription": "Periódico local de Monte Maíz.",
        "MoreInfoAt": "Más información aquí, en el Periódico local de Monte Maíz.",
        "TemplatePath": "templates",
        "WeatherSource": "accuweather:SAM|AR|AR005|MONTE MAIZ",
        "WeatherMeasureType": "1",
        "CurrencySource": "cotizacion-monedas:Dolar|Euro|Real",
        "TimesSingular": "vez",
        "TimesPlural": "veces"
    }
}

Quand j'essaye de le décoder avec json_decode(), il renvoie NULL. Pourquoi? Le fichier est lisible (j'ai essayé de faire écho file_get_contents()et cela a bien fonctionné).

J'ai testé JSON contre http://jsonlint.com/ et c'est parfaitement valide.

Quel est le problème ici?

Solution

Cherchant des réponses sur Google, je suis revenu à SO: json_decode renvoie NULL après un appel au service Web . Mon fichier JSON avait la séquence UTF BOM (certains caractères binaires qui ne devraient pas être là), cassant ainsi la structure JSON. Je suis allé à Hex Editor, j'ai effacé les octets. Tout est revenu à la normale. Pourquoi est-ce arrivé? Parce que j'ai édité le fichier à l'aide du bloc-notes de Microsoft Windows. Terrible idée!

Joel A. Villarreal Bertoldi
la source
5
Travailler avec PHP 5.2.9; donc, je ne peux pas utiliser json_last_error().
Joel A. Villarreal Bertoldi
1
Notez également que cela peut se produire avec d'autres caractères non valides au milieu du fichier. J'ai juste eu json_decode () renvoyant null parce que la chaîne contenait un de ces tirets spéciaux, probablement collé à partir de MS Word, puis peut-être mal codé. Pour identifier les caractères potentiellement problématiques, ouvrez le fichier JSON (que j'ai utilisé dans Notepad ++), modifiez l'encodage (sans conversion) et enregistrez-le en tant que copie. Puis différez les deux fichiers (j'ai utilisé WinMerge).
LinusR
(Problème de bloc-notes Windows) S'il vous plaît, consultez ceci, j'ai partagé le problème aussi et il l'a résolu: stackoverflow.com/questions/10290849/...
Felix Aballi
duplication possible de json_decode renvoie NULL après un appel au service Web
utilisateur
Pour moi, ce n'était rien de spécial, juste une virgule supplémentaire à la fin de l'élément d'un objet. À emporter: tout ce qui rend votre JSON incohérent va générer une erreur. Conseil bonus: ne faites pas confiance à jsonviewer.stack.hu Utilisez quelque chose comme jsonlint
Aman Alam

Réponses:

68

Cela peut être l'encodage des caractères spéciaux. Vous pouvez demander à json_last_error () d'obtenir des informations précises.

Mise à jour: Le problème est résolu, regardez le paragraphe "Solution" dans la question.

Pekka
la source
J'utilise les caractères spéciaux depuis que j'ai démarré l'application et il n'y avait aucun problème auparavant. Localement, le décodage JSON fonctionne parfaitement. Sur mon serveur, ce n'est pas le cas. Et je ne peux pas appeler json_last_error()car c'est PHP 5.2.9. Cette fonction apparaît sur PHP 5.3.0.
Joel A. Villarreal Bertoldi
1
Non, cela devrait fonctionner. Je ne peux pas faire d'autres tests pour le moment, si j'y reviens plus tard, je posterai ici. Il y a aussi quelques astuces dans les notes de l'utilisateur: de.php.net/json_decode peut-être que quelque chose aide.
Pekka
1
Pour moi, sur PHP 5.3, cela fonctionne bien lorsque le texte est encodé en UTF-8. Mais si je passe le texte en utf8_decode()premier, puis json_decode()échoue silencieusement.
Matthieu
1
@Pekka À la recherche de réponses sur Google, je suis retourné à SO: stackoverflow.com/questions/689185/json-decode-returns-null-php . Mon fichier JSON avait la séquence UTF BOM (certains caractères binaires qui ne devraient pas être là), cassant ainsi la structure JSON. Je suis allé à Hex Editor, j'ai effacé les octets. Tout est revenu à la normale. Pourquoi est-ce arrivé? Parce que j'ai édité le fichier à l'aide du bloc-notes de Micro $ oft Windows. Terrible idée!
Joel A. Villarreal Bertoldi
2
Cela devrait être signalé comme un bogue aux gens de PHP. Si la nomenclature était UTF8 valide, elle ne devrait pas s'étouffer silencieusement.
jmucchiello
86

Cela a fonctionné pour moi

json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $json_string), true );
Dunith Dhanushka
la source
2
J'ai utilisé ceci et j'ai obtenu le tableau mais mes caractères spécifiques à ma langue (ş, ç, ö, ..) ont également été supprimés.
zkanoca
5
Ce n'est pas correct si les données json sont encodées en UTF-8 (ou tout encodage UTF je suppose). Il supprimera les données valides encodées en UTF-8. Cela fonctionnera probablement tant que le fichier ne contient que de la langue anglaise, mais c'est toujours une hypothèse risquée. Je n'utiliserais pas ça.
DaedalusAlpha
Avec ça ça marche mais sans ça, même si les deux cordes sont identiques, est-ce que je manque quelque chose?
Rudie Visser
ça marche! mais pourquoi? la chaîne que j'ai essayé de décoder ne contenait aucun caractère spécial
Tobias Gassmann
Impressionnant. A travaillé pour moi. :)
Sohil
31

Vous pouvez essayer avec.

json_decode(stripslashes($_POST['data']))
Gabriel Castillo Prada
la source
J'ai accidentellement appelé stripslashes()deux fois, ce qui a supprimé les barres obliques essentielles et causé une chaîne JSON invalide. Cette réponse m'a aidé à repérer l'erreur
Philipp
22

Si vous vérifiez la demande dans Chrome, vous verrez que le JSON est du texte, donc un code vide a été ajouté au JSON.

Vous pouvez l'effacer en utilisant

$k=preg_replace('/\s+/', '',$k);

Ensuite, vous pouvez utiliser:

json_decode($k)

print_r affichera alors le tableau.

user2254008
la source
Merci pour cela - j'espère que vous trouverez votre anglais manquant.
Dean_Wilson
Mec, tu es une légende, tu te bats avec ça toute la journée.
Sboniso Marcus Nzimande
Je l'ai fait pour moi !! Un ajustement simple que j'ai fait est d'ajouter un espace dans le remplacement, je l'utilise et il semble également remplacer mon espace. fonctionne bien maintenant. $k=preg_replace('/\s+/', ' ',$k);
Kash
Le problème est que cela supprime chaque espace, ce qui rend le texte anglais tout collé n'est-ce pas?
CodeGuru
14

J'ai eu le même problème et je l'ai résolu simplement en remplaçant le caractère de citation avant le décodage.

$json = str_replace('"', '"', $json);
$object = json_decode($json);

Ma valeur JSON a été générée par la fonction JSON.stringify.

Yapp Ka Howe
la source
Dans ce cas, la fonction htmlspecialchars a peut-être été utilisée et le JSON ne peut plus être analysé. Pour l'inverser, il y a la fonction "htmlspecialchars_decode" au lieu de remplacer manuellement & quot;
Davy
11

Peut-être que certains personnages cachés dérangent votre json, essayez ceci:

$json = utf8_encode($yourString);
$data = json_decode($json);
Albert Abdonor
la source
Après avoir essayé toutes les solutions ci-dessus, celle-ci a finalement fonctionné pour moi. Merci beaucoup!!
Anis R.
7
$k=preg_replace('/\s+/', '',$k); 

l'a fait pour moi. Et oui, des tests sur Chrome. Thx à user2254008

Jürgen Math
la source
4

Je pensais juste ajouter ceci, car je suis tombé sur ce problème aujourd'hui. S'il y a un remplissage de chaîne autour de votre chaîne JSON, json_decode retournera NULL.

Si vous extrayez le JSON d'une source autre qu'une variable PHP, il serait sage de le «découper» d'abord:

$jsonData = trim($jsonData);
Phil LaNasa
la source
4

cela vous aide à comprendre quel est le type d'erreur

<?php
// A valid json string
$json[] = '{"Organization": "PHP Documentation Team"}';

// An invalid json string which will cause an syntax 
// error, in this case we used ' instead of " for quotation
$json[] = "{'Organization': 'PHP Documentation Team'}";


foreach ($json as $string) {
    echo 'Decoding: ' . $string;
    json_decode($string);

    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            echo ' - No errors';
        break;
        case JSON_ERROR_DEPTH:
            echo ' - Maximum stack depth exceeded';
        break;
        case JSON_ERROR_STATE_MISMATCH:
            echo ' - Underflow or the modes mismatch';
        break;
        case JSON_ERROR_CTRL_CHAR:
            echo ' - Unexpected control character found';
        break;
        case JSON_ERROR_SYNTAX:
            echo ' - Syntax error, malformed JSON';
        break;
        case JSON_ERROR_UTF8:
            echo ' - Malformed UTF-8 characters, possibly incorrectly encoded';
        break;
        default:
            echo ' - Unknown error';
        break;
    }

    echo PHP_EOL;
}
?>
Enrico Tempesti
la source
2

Gardez juste une fois. J'ai passé 3 heures à découvrir que c'était juste un problème d'encodage html. Essaye ça

if(get_magic_quotes_gpc()){
   $param = stripslashes($row['your column name']);
}else{
  $param = $row['your column name'];
}

$param = json_decode(html_entity_decode($param),true);
$json_errors = array(
JSON_ERROR_NONE => 'No error has occurred',
JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded',
JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
JSON_ERROR_SYNTAX => 'Syntax error',
);
echo 'Last error : ', $json_errors[json_last_error()], PHP_EOL, PHP_EOL;
print_r($param);
Samuel Kwame Antwi
la source
1

Comme indiqué par Jürgen Math en utilisant la méthode preg_replace répertoriée par user2254008, cela a également été corrigé pour moi.

Cela ne se limite pas à Chrome, il semble s'agir d'un problème de conversion de jeu de caractères (du moins dans mon cas, Unicode -> UTF8). Cela a résolu tous les problèmes que j'avais.

En tant que futur nœud, l'objet JSON que je décodais provenait de la fonction json.dumps de Python. Cela a à son tour provoqué la diffusion d'autres données insalubres bien qu'elles aient été facilement traitées.

Destreyf
la source
1

Si vous obtenez json de la base de données, mettez

mysqli_set_charset($con, "utf8");

après avoir défini le lien de connexion $ con

TomoMiha
la source
Merci TomoMiha. C'est exactement ce qui convient à tous mes problèmes avec MySQL contenant des caractères spéciaux et une fois converti par json_decode, ce champ particulier a été
renvoyé
1

Dans mon cas, c'est à cause du guillemet simple dans la chaîne JSON.

Le format JSON n'accepte que les guillemets doubles pour les clés et les valeurs de chaîne.

Exemple:

$jsonString = '{\'hello\': \'PHP\'}'; // valid value should be '{"hello": "PHP"}'
$json = json_decode($jsonString);
print $json; // null

Je suis confus à cause de la syntaxe Javascript. En Javascript, bien sûr, nous pouvons faire comme ceci:

let json = {
    hello: 'PHP' // no quote for key, single quote for string value
}

// OR:
json = {
    'hello': 'PHP' // single quote for key and value
}

mais plus tard, lors de la conversion de ces objets en chaîne JSON:

JSON.stringify(json); // "{"hello":"PHP"}"
Tho
la source
0

J'ai résolu ce problème en imprimant le JSON, puis en vérifiant la source de la page (CTRL / CMD + U):

print_r(file_get_contents($url));

Il s'est avéré qu'il y avait une <pre>balise de fin .

Jeffrey Roosendaal
la source
0

vous devez vous assurer de ces points

1. votre chaîne json ne contient aucun caractère inconnu

2. la chaîne json peut être vue depuis le visualiseur json en ligne (vous pouvez rechercher sur google en tant que visualiseur en ligne ou parser pour json), elle devrait afficher sans aucune erreur

3. votre chaîne n'a pas d'entités html, elle doit être du texte brut / chaîne

pour l'explication du point 3

$html_product_sizes_json=htmlentities($html);
    $ProductSizesArr = json_decode($html_product_sizes_json,true);

to (supprimer la fonction htmlentities ())

$html_product_sizes_json=$html;
    $ProductSizesArr = json_decode($html_product_sizes_json,true);
Hassan Saeed
la source
0

Pour moi, je devais désactiver le error_reporting , pour obtenir json_decode () fonctionne correctement. Cela semble étrange, mais vrai dans mon cas. Parce qu'il y a un avis imprimé entre la chaîne JSON que j'essaie de décoder.

shasi kanth
la source
0

La chose la plus importante à retenir, lorsque vous obtenez un résultat NULL à partir de données JSON qui est valide, est d'utiliser la commande suivante:

json_last_error_msg();

C'est à dire.

var_dump(json_last_error_msg());
string(53) "Control character error, possibly incorrectly encoded"

Vous corrigez ensuite cela avec:

$new_json = preg_replace('/[[:cntrl:]]/', '', $json);
Subvention
la source
0

Donc, html_entity_decode () a fonctionné pour moi. Veuillez essayer ceci.

$input = file_get_contents("php://input");
$input = html_entity_decode($input);
$event_json = json_decode($input,true);
Suman Deol
la source
-5
<?php 
$json_url = "http://api.testmagazine.com/test.php?type=menu";
$json = file_get_contents($json_url);
$json=str_replace('},

]',"}

]",$json);
$data = json_decode($json);

echo "<pre>";
print_r($data);
echo "</pre>";
?>
user2648057
la source