La mejor manera de almacenar JSON en un atributo HTML?


Necesito poner un objeto JSON en un atributo en un elemento HTML.

  1. El HTML no tiene que validarse.

    Respuesta de Quentin: Almacena el JSON en un atributo data-* , que es HTML5 válido.

  2. El objeto JSON podría ser de cualquier tamaño, es decir, enorme

    Respuesta de Maiku Mori: El límite para un atributo HTML es potencialmente 65536 caracteres .

  3. ¿Qué pasa si el JSON contiene caracteres especiales? e. g. {foo: '<"bar/>'}

    Answered by Quentin: Codifica la cadena JSON antes de colocarla en el atributo, según las convenciones habituales. Para PHP, utilice el htmlentities() función.


EDIT-Solución de ejemplo usando PHP y jQuery

Escribiendo el JSON en el atributo 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>

Recuperar el JSON usando 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);

});
Author: Community, 2011-09-06

7 answers

El HTML no tiene que validarse.

¿Por qué no? La validación es realmente fácil QA que detecta muchos errores. Utilice un atributo HTML 5 data-*.

El objeto JSON podría ser de cualquier tamaño (es decir, enorme).

No he visto ninguna documentación sobre los límites del navegador para los tamaños de atributos.

Si se encuentra con ellos, almacene los datos en un <script>. Defina un objeto y asigne elementos ida nombres de propiedad en ese objeto.

¿Qué pasa si el JSON contiene caracteres especiales? (por ejemplo, {test: ''})

Simplemente siga las reglas normales para incluir datos no confiables en los valores de atributos. Utilice &amp; y &quot; (si está envolviendo el valor del atributo entre comillas dobles) o &#x27; (si está envolviendo el valor del atributo entre comillas simples).

Tenga en cuenta, sin embargo, que eso no es JSON (que requiere que los nombres de propiedad sean cadenas y las cadenas se delimiten solo con comillas dobles).

 33
Author: Quentin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-16 06:17:18

Dependiendo de dónde lo pongas,{[39]]}

  • En un <div> como pidió, debe asegurarse de que el JSON no contenga especiales HTML que puedan iniciar una etiqueta, comentario HTML, doctype incrustado, etc. Necesita escapar al menos <, y & de tal manera que el carácter original no aparezca en la secuencia escapada.
  • En los elementos <script> debe asegurarse de que el JSON no contenga una etiqueta final </script> o un límite de texto de escape: <!-- o -->.
  • En caso de manejadores debe asegurarse de que el JSON conserve su significado incluso si tiene cosas que se parecen a entidades HTML y no rompe los límites de atributos (" o ').

Para los dos primeros casos (y para los analizadores JSON antiguos) debe codificar U+2028 y U+2029, ya que son caracteres de nueva línea en JavaScript, aunque están permitidos en cadenas sin codificar en JSON.

Para ser correcto, necesitas escapar \ y citar caracteres JSON y nunca es mala idea siempre codificar NUL.

Si el HTML se puede servir sin una codificación de contenido, debe codificar + para evitar ataques UTF-7.

En cualquier caso, la siguiente tabla de escape funcionará:

  • NUL - > \u0000
  • CR - > \n o \u000a
  • LF - > \r o \u000d
  • " -> \u0022
  • & -> \u0026
  • ' -> \u0027
  • + -> \u002b
  • / -> \/ o \u002f
  • < -> \u003c
  • > -> \u003e
  • \ -> \\ o \u005c
  • U+2028 -> \u2028
  • U + 2029 - > \u2029

Así que el valor de la cadena JSON para el texto Hello, <World>! con una nueva línea al final sería "Hello, \u003cWorld\u003e!\r\n".

 15
Author: Mike Samuel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-06 16:51:34

Otra forma de hacerlo es poner datos json dentro de la etiqueta <script>, pero no con type="text/javascript", sino con el tipo type="text/bootstrap" o type="text/json", para evitar la ejecución de javascript.

Entonces, en algún lugar de su programa, puede pedirlo de esta manera:

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;
  } 
}

En el lado del servidor, puede hacer algo como esto (este ejemplo con php y twig):

<script id="my_model" type="text/json">
  {{ my_model|json_encode()|raw }}
</script>
 9
Author: gobwas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-13 07:31:48

Puedes usar 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());

Salida

Nombre: Jayson Apellido: Monterroso

Compruebe esto: http://learn.knockoutjs.com /

 5
Author: jayM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-24 17:51:46

Otra opción es base64 codificar la cadena JSON y si necesita usarla en su javascript decodificarla con la función atob().

var data = JSON.parse(atob(base64EncodedJSON));
 3
Author: Pavel Petrov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-09 11:08:31

Nada elegante aquí. Desde PHP, ejecute la cadena JSON a través de htmlspecialchars para asegurarse de que no se puedan interpretar caracteres especiales como HTML. Desde Javascript, no es necesario escapar; simplemente establezca el atributo y estará listo.

 2
Author: Matchu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-06 15:56:46

Lo que puedes hacer es usar cdata alrededor de tu elemento/s de esta manera

<![CDATA[  <div class='log' mydata='${aL.logData}'>${aL.logMessage}</div>     ]]>  

Donde mydata es una cadena json sin procesar. Espero que esto te ayude a ti y a los demás.

 0
Author: Binaryrespawn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-07 15:04:49