202 votes

jQuery : citation unique dans la réponse JSON

J'envoie des requêtes à mon serveur en utilisant jQuery.post() et mon serveur renvoie des objets JSON (du type { "var": "value", ... } . Cependant, si l'une des valeurs contient un guillemet simple (correctement échappé comme \' ), jQuery ne parvient pas à analyser une chaîne JSON autrement valide. Voici un exemple de ce que je veux dire (réalisé dans la console de Chrome) :

Chrome Console

Est-ce normal ? N'y a-t-il aucun moyen de transmettre correctement une citation unique via JSON ?

325voto

Justin Ethier Points 57486

Selon le diagramme de la machine à états sur le Site web JSON Dans le cas d'un système de gestion de l'information, seuls les guillemets doubles échappés sont autorisés, et non les guillemets simples. Les guillemets simples n'ont pas besoin d'être échappés :

http://www.json.org/string.gif

Mise à jour - Plus d'informations pour ceux qui sont intéressés :


Douglas Crockford ne dit pas spécifiquement pourquoi la spécification JSON n'autorise pas les guillemets simples échappés dans les chaînes de caractères. Cependant, au cours de sa discussion sur JSON dans le document Annexe E de JavaScript : Les bons côtés Il écrit :

Les objectifs de conception de JSON étaient d'être minimalistes, portables, textuels et un sous-ensemble de JavaScript. Moins nous avons besoin de nous mettre d'accord pour interagir, plus nous pouvons interagir facilement.

Il a donc peut-être décidé de n'autoriser la définition des chaînes qu'à l'aide de guillemets doubles, car cela représente une règle de moins sur laquelle toutes les implémentations JSON doivent s'accorder. Par conséquent, il est impossible qu'un simple caractère guillemet dans une chaîne de caractères termine accidentellement la chaîne, car par définition, une chaîne de caractères ne peut être terminée que par un caractère guillemet double. Il n'est donc pas nécessaire d'autoriser l'échappement d'un caractère guillemet simple dans la spécification formelle.


En creusant un peu plus, Crockford's org.json L'implémentation de JSON pour Java est plus permise et plus efficace. fait autorisent les caractères guillemets simples :

Les textes produits par les méthodes toString sont strictement conformes aux règles de syntaxe JSON. Les constructeurs sont plus indulgents quant aux textes qu'ils acceptent :

...

  • Les chaînes de caractères peuvent être citées avec ' (guillemet simple).

Ceci est confirmé par le JSONTokener code source. Le site nextString accepte les caractères guillemets simples échappés et les traite comme des caractères guillemets doubles :

public String nextString(char quote) throws JSONException {
    char c;
    StringBuffer sb = new StringBuffer();
    for (;;) {
        c = next();
        switch (c) {

        ...

        case '\\':
            c = this.next();
            switch (c) {

            ...

            case '"':
            case '\'':
            case '\\':
            case '/':
                sb.append(c);
                break;
        ...

En haut de la méthode se trouve un commentaire informatif :

Le format JSON formel n'autorise pas les chaînes entre guillemets simples, mais une implémentation est autorisée à les accepter.

Certaines implémentations acceptent donc les guillemets simples, mais il ne faut pas s'y fier. De nombreuses implémentations populaires sont assez restrictives à cet égard et rejetteront JSON qui contient des chaînes entre guillemets simples et/ou des guillemets simples échappés.


Enfin, pour en revenir à la question initiale, jQuery.parseJSON tente d'abord d'utiliser le parseur JSON natif du navigateur ou une bibliothèque chargée telle que json2.js le cas échéant (qui, soit dit en passant, est la bibliothèque sur laquelle la logique de jQuery est basée si JSON n'est pas défini). Ainsi, jQuery ne peut être aussi permissif que cette mise en œuvre sous-jacente :

parseJSON: function( data ) {
    ...

    // Attempt to parse using the native JSON parser first
    if ( window.JSON && window.JSON.parse ) {
        return window.JSON.parse( data );
    }

    ...

    jQuery.error( "Invalid JSON: " + data );
},

Pour autant que je sache, ces implémentations n'adhèrent qu'à la spécification officielle de JSON et n'acceptent pas les guillemets simples, donc jQuery non plus.

16voto

slf Points 15327

Si vous avez besoin d'un guillemet simple à l'intérieur d'une chaîne de caractères, puisque \' n'est pas défini par la spécification, utilisez \u0027 voir http://www.utf8-chartable.de/ pour tous

5voto

Erik Čerpnjak Points 121

Je comprends où se situe le problème et lorsque je regarde les spécifications, il est clair que les guillemets simples non encapsulés doivent être analysés correctement.

J'utilise la fonction jQuery.parseJSON pour analyser la chaîne JSON mais j'obtiens toujours une erreur d'analyse lorsqu'il y a un guillemet simple dans les données préparées avec json_encode.

Serait-ce une erreur dans mon implémentation qui ressemble à ceci (PHP - côté serveur) :

$data = array();

$elem = array();
$elem['name'] = 'Erik';
$elem['position'] = 'PHP Programmer';
$data[] = json_encode($elem);

$elem = array();
$elem['name'] = 'Carl';
$elem['position'] = 'C Programmer';
$data[] = json_encode($elem);

$jsonString = "[" . implode(", ", $data) . "]";

L'étape finale consiste à stocker la chaîne encodée JSON dans une variable JS :

<script type="text/javascript">
employees = jQuery.parseJSON('<?=$marker; ?>');
</script>

Si j'utilise "" au lieu de '', il y a toujours une erreur.

SOLUTION :

La seule chose qui a fonctionné pour moi a été d'utiliser le masque de bits JSON_HEX_APOS pour convertir les guillemets simples comme ceci :

json_encode($tmp, JSON_HEX_APOS);

Existe-t-il un autre moyen de résoudre ce problème ? Mon code est-il erroné ou mal écrit ?

Remerciements

3voto

BehranG BinA Points 114

Lorsque vous envoyez une seule citation dans une requête

empid = " T'via"
empid =escape(empid)

Lorsque vous obtenez la valeur en incluant une seule citation

var xxx  = request.QueryString("empid")
xxx= unscape(xxx)

Si vous voulez rechercher/insérer la valeur qui comprend une citation unique dans une requête xxx=Replace(empid, "'", "''")

2voto

chopstik Points 74

J'ai rencontré un problème similaire en utilisant CakePHP pour sortir un bloc JavaScript script en utilisant la fonction native PHP json_encode . $contractorCompanies contient des valeurs qui ont des guillemets simples et comme expliqué ci-dessus et attendu json_encode($contractorCompanies) ne les échappe pas car il s'agit d'un JSON valide.

<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".(json_encode($contractorCompanies)."' );"); ?>

En ajoutant des addlashes() autour de la chaîne encodée JSON, vous échappez aux guillemets, ce qui permet à Cake / PHP de renvoyer le bon javascript au navigateur. Les erreurs JS disparaissent.

<?php $this->Html->scriptBlock("var contractorCompanies = jQuery.parseJSON( '".addslashes(json_encode($contractorCompanies))."' );"); ?>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X