問題描述
我需要將 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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。