web-dev-qa-db-fra.com

Meilleur moyen de stocker JSON dans un attribut HTML?

J'ai besoin de mettre un objet JSON dans un attribut d'un élément HTML.

  1. Le HTML n'a pas à valider.

    Répondu par Quentin: stocke le JSON dans un attribut data-* }, qui est valide en HTML5.

  2. 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 }.

  3. 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);

});
98
BadHorsie

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 ids 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 &amp; et &quot; (si vous mettez la valeur de l’attribut entre guillemets) ou &#x27; (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).

34
Quentin

En fonction de l'endroit où vous le mettez,

  • Dans un <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.
  • Dans les éléments <script>, vous devez vous assurer que le JSON ne contient pas de balise de fin </script> ni de limite de texte d'échappement: <!-- ou -->.
  • Dans les gestionnaires d'événements, vous devez vous assurer que le JSON conserve sa signification même s'il contient des éléments qui ressemblent à des entités HTML et ne casse pas les limites d'attribut (" 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:

  • NUL -> \u0000
  • CR -> \n ou \u000a
  • LF -> \r ou \u000d
  • " -> \u0022
  • & -> \u0026
  • ' -> \u0027
  • + -> \u002b
  • / -> \/ ou \u002f
  • < -> \u003c
  • > -> \u003e
  • \ -> \\ ou \u005c
  • + 2028 -> \u2028
  • U + 2029 -> \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".

15
Mike Samuel

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>
9
gobwas

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/

5
jayM

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));
5
Pavel Petrov

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.

2
Matchu

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.

0
Binaryrespawn

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>";
?>
0
Matthew D Auld