在 HTML 属性中存储 JSON 的最佳方式?

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

  1. HTML 不需要验证。

    答案是 Quentin: 将 JSON 存储在 data-*属性中,这是有效的 HTML5。

  2. JSON 对象可以是任何大小-即巨大的

    回答者: Maiku Mori。

  3. 如果 JSON 包含特殊字符会怎样? 例如 {foo: '<"bar/>'}

    Answered by Quentin: Encode the JSON string before putting it into the attribute, as per the usual conventions. 对于 PHP,使用 htmlentities() < em > 函数.


EDIT-使用 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);


});
108115 次浏览

这里没什么特别的。从 PHP 开始,在 htmlspecialchars中运行 JSON 字符串,以确保没有特殊字符可以被解释为 HTML。从 Javascript 中,不需要转义; 只需设置属性就可以了。

HTML 不需要验证。

为什么不呢? 验证真的很简单,QA 可以捕捉到很多错误。使用 HTML5data-*属性。

JSON 对象可以是任意大小(即巨大的)。

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

如果您遇到它们,那么将数据存储在 <script>中。定义一个对象并将元素 id映射到该对象中的属性名。

如果 JSON 包含特殊字符怎么办? (例如{ test:’< “ myString/>”})

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

但是请注意,这不是 JSON (它要求属性名是字符串,字符串只能用双引号分隔)。

取决于你把它放在哪里,

  • 按照您的要求,在 <div>中,您需要确保 JSON 不包含可以启动标记、 HTML 注释、嵌入式 doctype 等的 HTML 特殊功能。至少需要转义 <&,以使原始字符不出现在转义序列中。
  • <script>元素中,需要确保 JSON 不包含结束标记 </script>或转义文本边界: <!---->
  • 在事件处理程序中,您需要确保 JSON 保留其含义,即使它具有类似于 HTML 实体的内容,并且不会破坏属性边界("')。

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

为了正确起见,您需要转义 \和 JSON 引用字符,并且总是编码 NUL 永远不是一个坏主意。

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

在任何情况下,下面的转义表都可以工作:

  • NUL-> \u0000
  • CR-> \n\u000a
  • 低频-> \r\u000d
  • - > \u0022
  • - > \u0026
  • - > \u0027
  • + -> \u002b
  • - > \/\u002f
  • - > \u003c
  • - > \u003e
  • - > \\\u005c
  • U+2028 -> \u2028
  • U + 2029-> \u2029

So the JSON string value for the text Hello, <World>! with a newline at the end would be "Hello, \u003cWorld\u003e!\r\n".

你可以用美女,

<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/

What you can do is use cdata around your element/s like this

<![CDATA[  <div class='log' mydata='${aL.logData}'>${aL.logMessage}</div>     ]]>

其中 mydata 是一个原始的 json 字符串。希望这对您和其他人有所帮助。

另一种方法是将 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;
}
}

On server side, you can do something like this (this example with php and 小树枝):

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

另一种选择是 base64编码 JSON 字符串,如果需要在 javascript 中使用它,则使用 atob()函数对其进行解码。

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

可以使用的另一种思想是将 JSON 数据作为 base64字符串存储在属性中,然后使用 window.atobwindow.btoa将其还原为可用的 JSON 数据。

<?php
$json = array("data"=>"Some json data thing");
echo "<div data-json=\"".base64_encode(json_encode($json))."\"></div>";
?>

对于简单的 JSON 对象,下面的代码可以工作。

编码:

var jsonObject = { numCells: 5, cellWidth: 1242 };
var attributeString = escape(JSON.stringify(jsonObject));

译码:

var jsonString = unescape(attributeString);
var jsonObject = JSON.parse(jsonString);

在我们的例子中,将 '替换为 &#39;,并在简单引号之间插入 json 对 vue 非常有效:

译者:

$data = json_encode($data);
$data = preg_replace("/'/", '&#39;', $data);

Html:

<vue_tag :data='<?=$json?>' />