問題描述

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