J'ai besoin de mettre un objet JSON dans un attribut d'un élément HTML.
Le HTML n'a pas à valider.
Répondu par Quentin: stocke le JSON dans un attribut data-*
}, qui est valide en HTML5.
L’objet JSON peut avoir n’importe quelle taille - c’est-à-dire énorme
Réponse de Maiku Mori: La limite pour un attribut HTML est potentiellement de 65 536 caractères }.
Et si le JSON contient des caractères spéciaux? par exemple.{foo: '<"bar/>'}
Répondu par Quentin: Encodez la chaîne JSON avant de la placer dans l'attribut, conformément aux conventions habituelles. Pour PHP, utilisez la fonctionhtmlentities()
} _.
EDIT - Exemple de solution utilisant PHP et jQuery
Écrire le JSON dans l'attribut HTML:
<?php
$data = array(
'1' => 'test',
'foo' => '<"bar/>'
);
$json = json_encode($data);
?>
<a href="#" data-json="<?php echo htmlentities($json, ENT_QUOTES, 'UTF-8'); ?>">CLICK ME</a>
Récupérer le JSON en utilisant jQuery:
$('a').click(function() {
// Read the contents of the attribute (returns a string)
var data = $(this).data('json');
// Parse the string back into a proper JSON object
var json = $.parseJSON($(this).data('json'));
// Object now available
console.log(json.foo);
});
Le HTML n'a pas à valider.
Pourquoi pas? La validation est vraiment facile Une assurance qualité qui détecte de nombreuses erreurs. Utilisez un attribut HTML 5 data-*
.
L’objet JSON peut être n’importe quelle taille (c’est-à-dire énorme).
Je n'ai pas vu de documentation sur les limites du navigateur pour attribuer des tailles.
Si vous les rencontrez, stockez les données dans un <script>
. Définissez un objet et mappez l'élément id
s sur les noms de propriétés de cet objet.
Et si le JSON contient des caractères spéciaux? (exemple: {test: '<"myString />'})
Suivez simplement les règles habituelles pour inclure des données non fiables dans les valeurs d'attribut. Utilisez &
et "
(si vous mettez la valeur de l’attribut entre guillemets) ou '
(si vous mettez la valeur de l’attribut entre guillemets).
Notez cependant qu'il ne s'agit pas de JSON (ce qui nécessite que les noms de propriété soient des chaînes et que les chaînes ne soient délimitées que par des guillemets).
En fonction de l'endroit où vous le mettez,
<div>
comme vous l'avez demandé, vous devez vous assurer que le JSON ne contient pas de code HTML spécial pouvant démarrer une balise, un commentaire HTML, un doctype intégré, etc. Vous devez échapper au moins <
, et &
de manière à ce que le caractère d'origine n'apparaisse pas dans la séquence d'échappement.<script>
, vous devez vous assurer que le JSON ne contient pas de balise de fin </script>
ni de limite de texte d'échappement: <!--
ou -->
."
ou '
).Pour les deux premiers cas (et pour les anciens analyseurs JSON), vous devez coder U + 2028 et U + 2029 car il s'agit de caractères de nouvelle ligne en JavaScript, même s'ils sont autorisés dans les chaînes non codées en JSON.
Pour être correct, vous devez éviter les caractères \
et les guillemets JSON. Ce n'est jamais une mauvaise idée de toujours encoder NUL.
Si le code HTML peut être servi sans codage de contenu, vous devez coder +
pour empêcher attaques UTF-7 .
Dans tous les cas, la table d'échappement suivante fonctionnera:
\u0000
\n
ou \u000a
\r
ou \u000d
"
-> \u0022
&
-> \u0026
'
-> \u0027
+
-> \u002b
/
-> \/
ou \u002f
<
-> \u003c
>
-> \u003e
\
-> \\
ou \u005c
\u2028
\u2029
Ainsi, la valeur de chaîne JSON pour le texte Hello, <World>!
avec une nouvelle ligne à la fin serait "Hello, \u003cWorld\u003e!\r\n"
.
Une autre façon de le faire est de placer les données json dans la balise <script>
, mais pas avec type="text/javascript"
, mais avec le type type="text/bootstrap"
ou type="text/json"
, afin d'éviter l'exécution de javascript.
Ensuite, à un endroit de votre programme, vous pouvez le demander de la manière suivante:
function getData(key) {
try {
return JSON.parse($('script[type="text/json"]#' + key).text());
} catch (err) { // if we have not valid json or dont have it
return null;
}
}
Du côté du serveur, vous pouvez faire quelque chose comme ceci (cet exemple avec php et twig ):
<script id="my_model" type="text/json">
{{ my_model|json_encode()|raw }}
</script>
Vous pouvez utiliser knockoutjs,
<p>First name: <strong data-bind="text: firstName" >todo</strong></p>
<p>Last name: <strong data-bind="text: lastName">todo</strong></p>
knockout.js
// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
this.firstName = "Jayson";
this.lastName = "Monterroso";
}
// Activates knockout.js
ko.applyBindings(new AppViewModel());
Sortie
Prénom: Jayson Nom: Monterroso
Vérifiez ceci: http://learn.knockoutjs.com/
Une autre option consiste à coder en base64 la chaîne JSON et, si vous avez besoin de l’utiliser dans votre javascript, décodez-la avec la fonction atob()
.
var data = JSON.parse(atob(base64EncodedJSON));
Rien d'extraordinaire ici. Depuis PHP, exécutez htmlspecialchars
dans la chaîne JSON pour vous assurer qu'aucun caractère spécial ne peut être interprété en tant que HTML. De Javascript, aucune évasion nécessaire; il suffit de définir l'attribut et vous êtes prêt à partir.
Ce que vous pouvez faire est d'utiliser cdata autour de votre/vos élément (s) comme ceci
<![CDATA[ <div class='log' mydata='${aL.logData}'>${aL.logMessage}</div> ]]>
où mydata est une chaîne json brute. J'espère que cela vous aide et aide les autres.
Vous pouvez également utiliser les données JSON sous forme de chaîne base64 dans l'attribut, puis utiliser window.atob
ou window.btoa
pour le restaurer en données JSON utilisables.
<?php
$json = array("data"=>"Some json data thing");
echo "<div data-json=\"".base64_encode(json_encode($json))."\"></div>";
?>