问题描述
我需要将 JSON 对象放入 HTML 元素的属性中。
-
HTML 不必验证。由 Quentin 回答:将 JSON 存储在
data-*属性中,这是有效的 HTML5 。 -
JSON 对象可以是任何大小 – 即由 Maiku Mori:The limit for an HTML attribute is potentially 65536 characters 回答的巨大的数据。
-
如果 JSON 包含特殊字符怎么办?例如
{foo: '<"bar/>'}由 Quentin 回答:根据常规惯例,将 JSON 字符串放入属性之前进行编码。 For PHP, use thehtmlentities()功能。
编辑 – 使用 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/>’})
只需遵循在属性值中包含不受信任数据的常规规则。使用& 和"(如果您将属性值包含在双引号中) 或'(如果您将属性值包含在单引号中) 。
但是请注意,这不是 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 – >
n或u000a -
LF – >
r或u000d -
"– >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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。