我需要把一个JSON对象放到一个HTML元素的属性中。
-
HTML不需要验证answer by Quentin:将JSON存储在
data-*
属性中,这是有效的HTML5 -
JSON对象可以是任何大小-即巨大的
HTML属性的限制可能是65536个字符
-
如果JSON包含特殊字符怎么办?例:
{foo: '<"bar/>'}
answer by Quentin:按照通常的惯例,在将JSON字符串放入属性之前对其进行编码。对于PHP,使用
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);
});
HTML不需要验证
为什么不呢?验证是非常简单的QA,它可以捕获许多错误。使用HTML 5 data-*
属性
JSON对象可以是任意大小(即巨大)。
我还没有看到任何关于浏览器限制属性大小的文档。
如果你遇到它们,那么将数据存储在<script>
中。定义一个对象,并将元素id
s映射到该对象中的属性名。
如果JSON包含特殊字符怎么办?(例如{test: '<"myString/>'})
只需遵循在属性值中包含不可信数据的常规规则。使用&
和"
(如果你用双引号包装属性值)或'
(如果你用单引号包装属性值)。
另一种方法是将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>
取决于你把它放在哪里,
- 在
<div>
中,如您所要求的,您需要确保JSON不包含可以启动标签,HTML注释,嵌入doctype等的HTML特殊内容。您至少需要转义<
和&
,以使原始字符不出现在转义序列中。 - 在
<script>
元素中,您需要确保JSON不包含结束标签</script>
或转义文本边界:<!--
或-->
。 - 在事件处理程序中,您需要确保JSON保留其含义,即使它有看起来像HTML实体的东西,并且不打破属性边界(
"
或'
)。
对于前两种情况(以及旧的JSON解析器),您应该编码U+2028和U+2029,因为它们在JavaScript中是换行字符,即使它们在JSON中未编码的字符串中是允许的。
为了正确起见,您需要转义'
和JSON引号字符,并且始终编码NUL永远不是一个坏主意。
如果HTML可能没有内容编码,你应该编码+
来防止UTF-7攻击。
在任何情况下,下面的转义表都可以工作:
- null ->
'u0000
- CR ->
'n
或'u000a
- LF ->
'r
或'u000d
-
"
->'u0022
-
&
->'u0026
-
'
->'u0027
-
+
->'u002b
-
/
->'/
或'u002f
-
<
->'u003c
-
>
->'u003e
-
'
->''
或'u005c
- u +2028 ->
'u2028
- u +2029 ->
'u2029
所以JSON字符串值的文本Hello, <World>!
与换行在结束将是"Hello, 'u003cWorld'u003e!'r'n"
.
另一个选择是base64编码JSON字符串,如果你需要使用它在你的javascript解码它与atob()
函数。
var data = JSON.parse(atob(base64EncodedJSON));
对于简单的JSON对象,下面的代码可以工作。
编码:
var jsonObject = { numCells: 5, cellWidth: 1242 };
var attributeString = escape(JSON.stringify(jsonObject));
解码:
var jsonString = unescape(attributeString);
var jsonObject = JSON.parse(jsonString);
你可以使用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/
这里没什么特别的。在PHP中,通过htmlspecialchars
运行JSON字符串,以确保没有特殊字符可以被解释为HTML。从Javascript中,不需要转义;只要设置属性,就可以了。
另一个可以使用的想法是将JSON数据作为base64字符串存储在属性中,然后使用window.atob
或window.btoa
将其恢复为可用的JSON数据。
<?php
$json = array("data"=>"Some json data thing");
echo "<div data-json='"".base64_encode(json_encode($json))."'"></div>";
?>
你所能做的就是像这样在元素/s周围使用cdata
<![CDATA[ <div class='log' mydata='${aL.logData}'>${aL.logMessage}</div> ]]>
,其中mydata是一个原始json字符串。希望这对你和其他人有所帮助。
在我们的例子中,用'
替换'
,在简单的引号之间插入json对vue来说是完美的:
$data = json_encode($data);
$data = preg_replace("/'/", ''', $data);
html: <vue_tag :data='<?=$json?>' />