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

Bad*_*sie 105 html javascript php json

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

  1. HTML不必验证.

    Quentin回答:将JSON存储在data-*属性中,该属性是有效的HTML5.

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

    由Maiku Mori回答:HTML属性的限制可能是65536个字符.

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

    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>
Run Code Online (Sandbox Code Playgroud)

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

});
Run Code Online (Sandbox Code Playgroud)

Que*_*tin 37

HTML不必验证.

为什么不?验证非常简单QA可以捕获很多错误.使用HTML 5 data-*属性.

JSON对象可以是任何大小(即巨大的).

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

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

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

只需按照常规规则在属性值中包含不受信任的数据即可.使用&amp;&quot;(如果您将属性值包装在双引号中)或&#x27;(如果您将属性值包装在单引号中).

但请注意,这不是JSON(要求属性名称为字符串,字符串仅用双引号分隔).

  • *所以你说我应该在将它放入HTML属性之前做html_encode($ json)?* - 如果你使用的是PHP,那么这样就行了.*当我想在jQuery中读取它时,如何解码?* - 从属性解码?浏览器在将HTML解析为DOM时会执行此操作.*然后我如何使用jQuery以与在PHP中相同的方式将其写回来?* - 您正在设置DOM节点的属性,而不是生成原始HTML,浏览器将负责处理它. (6认同)
  • 所以你说我应该在将它放入HTML属性之前做`htmlentities($ json)` 然后,当我想在jQuery中读取它时,如何解码?然后我如何使用jQuery以与PHP相同的方式将其写回来? (5认同)
  • 目前,我遇到了一个问题,即我的浏览器目前无法在 Google Chrome 上对其进行解码,当我解析 JSON 时,所有 HTML 实体都在那里并且失败了。 (2认同)

Mik*_*uel 15

取决于你放在哪里,

  • <div>你问的时候,你需要确保JSON不包含可以启动标签,HTML注释,嵌入式文档类型等的HTML特价.你至少需要逃避<,并且&这样的方式使得原始角色不会出现在转义序列中.
  • <script>元素中,您需要确保JSON不包含结束标记</script>或转义文本边界:<!---->.
  • 在事件处理程序中,您需要确保JSON保留其含义,即使它具有看起来像HTML实体的东西并且不会破坏属性边界("').

对于前两种情况(以及对于旧的JSON解析器),您应该对U + 2028和U + 2029进行编码,因为这些是JavaScript中的换行符,即使它们在JSON中未编码的字符串中被允许.

为了正确,你需要转义\和JSON引用字符,总是编码NUL永远不是一个坏主意.

如果可以在没有内容编码的情况下提供HTML,则应进行编码+以防止UTF-7攻击.

无论如何,以下转义表将起作用:

  • 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, \u003cWorld\u003e!\r\n".


gob*_*was 12

你可以这样做的另一种方法 - 将json数据放在<script>tag中,但不能使用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;
  } 
}
Run Code Online (Sandbox Code Playgroud)

在服务器端,你可以做这样的事情(这个例子用php和twig):

<script id="my_model" type="text/json">
  {{ my_model|json_encode()|raw }}
</script>
Run Code Online (Sandbox Code Playgroud)

  • 该答案包含错误/危险信息!更改脚本类型不会修改&lt;/ script&gt;标记的检测。只需尝试:`&lt;script type =“ application / json” id =“ MyData”&gt;“ abc &lt;/ script&gt; &lt;script&gt; alert()&lt;/ script&gt;” &lt;/ script&gt;` (2认同)

Pav*_*rov 6

另一个选择是base64编码JSON字符串,如果你需要在你的javascript中使用它解码它与atob()函数.

var data = JSON.parse(atob(base64EncodedJSON));
Run Code Online (Sandbox Code Playgroud)

  • 当心-如果JSON包含非拉丁字符,则不起作用。 (2认同)

Cra*_*lot 6

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

编码:

var jsonObject = { numCells: 5, cellWidth: 1242 };
var attributeString = escape(JSON.stringify(jsonObject));
Run Code Online (Sandbox Code Playgroud)

解码:

var jsonString = unescape(attributeString);
var jsonObject = JSON.parse(jsonString);
Run Code Online (Sandbox Code Playgroud)


小智 5

你可以使用knockoutjs,

<p>First name: <strong data-bind="text: firstName" >todo</strong></p>
<p>Last name: <strong data-bind="text: lastName">todo</strong></p>
Run Code Online (Sandbox Code Playgroud)

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());
Run Code Online (Sandbox Code Playgroud)

产量

名:Jayson姓:Monterroso

检查一下:http: //learn.knockoutjs.com/