问题描述

我需要将 JSON 对象放入 HTML 元素的属性中。

  1. HTML 不必验证。由 Quentin 回答:将 JSON 存储在 data-*属性中,这是有效的 HTML5 。

  2. JSON 对象可以是任何大小 – 即由 Maiku Mori:The limit for an HTML attribute is potentially 65536 characters 回答的巨大的数据。

  3. 如果 JSON 包含特殊字符怎么办?例如 {foo: '<"bar/>'}由 Quentin 回答:根据常规惯例,将 JSON 字符串放入属性之前进行编码。 For PHP, use the htmlentities()功能。


编辑 – 使用 PHP 和 jQuery 的示例解决方案

将 JSON 写入 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>

使用 jQuery 检索 JSON:

$('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);

});

最佳解决方案

The HTML does not have to validate.

为什么不?验证真的很容易 QA 抓住了很多错误。使用 HTML 5 data-*属性。

The JSON object could be any size (i.e. huge).

我没有看到有关浏览器限制的属性大小的文档。

如果您遇到这种情况,请将数据存储在<script> 中。将对象和映射元素 id 定义到该对象中的属性名称。

What if the JSON contains special characters? (e.g. {test: ‘<“myString/>’})

只需遵循在属性值中包含不受信任数据的常规规则。使用&amp;&quot;(如果您将属性值包含在双引号中) 或'(如果您将属性值包含在单引号中) 。

但是请注意,这不是 JSON(需要属性名称是字符串和字符串仅用双引号分隔) 。

次佳解决方案

根据你所在的地方,

  • <div> 中,您需要确保 JSON 不包含可以启动标签,HTML 注释,嵌入式手册等的 HTML 特殊版本。您需要至少逃脱<&,以使原始字符不会出现在转义的序列中。

  • <script> 元素中,您需要确保 JSON 不包含结束标记</script> 或转义文本边界:<!---->

  • 在事件处理程序中,您需要确保 JSON 保留其含义,即使它具有看起来像 HTML 实体的东西,也不会破坏属性边界 ("') 。

对于前两种情况 (对于旧的 JSON 解析器),您应该对 U + 2028 和 U + 2029 进行编码,因为它们是 JavaScript 中的换行符,即使它们被允许在 JSON 中未编码的字符串中。

为了正确,您需要转义和 JSON 引号字符,并且始终编码 NUL 是永远不错的主意。

如果 HTML 可能没有内容编码,您应该编码+以防止 UTF-7 attacks

在任何情况下,以下转义表将工作:

  • NUL – > u0000

  • CR – > nu000a

  • LF – > ru000d

  • " – > u0022

  • & – > u0026

  • ' – > u0027

  • + – > u002b

  • / – > /u002f

  • < – > u003c

  • > – > u003e

  • – > \u005c

  • U+2028 – > u2028

  • U + 2029 – > u2029

所以文本 Hello, <World>! 的 JSON 字符串值与最后的换行符是"Hello, u003cWorldu003e!rn"

第三种解决方案

另一种方法可以将 Json 数据放在<script> 标签中,但不能使用 type="text/javascript",而是使用 type="text/bootstrap"type="text/json"类型,以避免 javascript 执行。

然后,在你的程序的某个地方,你可以这样问:

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

在服务器端,你可以这样做 (这个例子是 php 和 twig):

<script id="my_model" type="text/json">
  {{ my_model|json_encode()|raw }}
</script>

第四种方案

你可以使用 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());

产量

名字:Jayson 姓:Monterroso

检查:http://learn.knockoutjs.com/

第五种方案

另一个选择是对 JSON 字符串进行 base64 编码,如果需要在 JavaScript 中使用它与 atob()函数进行编码。

var data = JSON.parse(atob(base64EncodedJSON));

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛