JSONをHTML属性に格納する最良の方法は?


112

JSONオブジェクトをHTML要素の属性に配置する必要があります。

  1. HTMLは検証する必要はありません。

    Quentinによる回答:JSONをdata-*属性に格納します。これは有効なHTML5です。

  2. JSONオブジェクトは任意のサイズ-つまり巨大

    森まいくの回答: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>

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

});

おそらくその理由を説明し、別の解決策を求める必要があります。これが最善ではないと確信しているからです。data-something属性を使用することはできますが、「巨大な」量のテキストを保持できるかどうかはわかりません。特殊文字については、テキストをエンコード(escape()およびunescape())するだけです。

うん制限は65536文字(あるstackoverflow.com/questions/2752457/...
Maiku森

1
ところで、属性に名前data-jsonを付ける場合$(this).data('json')は、を使用する必要があります。jQueryはその部分をカバーしています。
Ciantic 2013

ただ注意してください。jsonにデータサフィックスを付ける必要はありません。有効なjsonをdata-custom_attributeに配置すると、jQueryで正常に動作します。
Garet Claborn 2014

中括弧のシーケンスを修正してください)}; =>});
MotsManish 2016年

回答:


41

HTMLは検証する必要はありません。

何故なの?検証は非常に簡単なQAであり、多くのミスをキャッチします。HTML 5 data-*属性を使用します。

JSONオブジェクトは任意のサイズ(つまり、巨大)にすることができます。

ブラウザでの属性サイズの制限に関するドキュメントを見たことがありません。

それらに遭遇した場合は、データをに保存します<script>。オブジェクトを定義し、idそのオブジェクトのプロパティ名に要素をマップします。

JSONに特殊文字が含まれている場合はどうなりますか?(例:{test: '<"myString />'})

信頼できないデータを属性値に含めるための通常のルールに従ってください。使用&amp;して&quot;(あなたが二重引用符で属性値をラップしている場合)または&#x27;(もしあなたしているラッピング単一引用符で属性値)。

ただし、これはJSONではないことに注意してください(プロパティ名は文字列で、文字列は二重引用符で区切る必要があります)。


5
それでhtmlentities($json)、それをHTML属性に入れる前に私がやるべきだと言っているのですか?そして、jQueryでそれを読みたいときに、それをどのようにデコードしますか?それから、jQueryを使用してPHPと同じように書き戻すにはどうすればよいですか?
BadHorsie

6
それで、HTML属性に入れる前にhtml_encode($ json)を実行する必要があると言っているのですか?— PHPを使用している場合は、それでうまくいきます。そして、jQueryでそれを読みたいときに、それをどのようにデコードしますか?—属性からデコードしますか?ブラウザはHTMLをDOMに解析するときにそれを行います。それから、jQueryを使用してPHPと同じように書き戻すにはどうすればよいですか?—生のHTMLを生成せずにDOMノードの属性を設定している場合、ブラウザが処理します。
クエンティン

1
現時点では、ブラウザが現在Google Chromeでデコードしていないという問題があり、JSONを解析しようとすると、すべてのHTMLエンティティがそこにあり、失敗します。
Bradley Weston

スクリプトタグ内に配置する場合は、スクリプトタグの特別な処理のため、別の方法でエスケープする必要があります。たとえば、</ script>が含まれている値は、scriptタグを終了します。
Dobes Vandermeer

16

どこに置くかによって、

  • では<div>、あなたはあなたが、少なくともエスケープする必要があるなど、JSONはタグ、HTMLのコメント、埋め込まれたDOCTYPEを開始することができますHTMLのスペシャルが含まれていないことを確認する必要があり、尋ねたとして<、そして&元の文字がないようにエスケープシーケンスに表示されます。
  • では<script>要素あなたはJSONは終了タグが含まれていないことを確認する必要があります</script>:またはテキスト境界エスケープ<!--かを-->
  • イベントハンドラーでは、HTMLエンティティのように見え、属性の境界("または')を壊さないものがある場合でも、JSONがその意味を保持するようにする必要があります。

最初の2つのケース(および古いJSONパーサー)では、U + 2028とU + 2029をエンコードする必要があります。これらは、JSONでエンコードされていない文字列で許可されていても、JavaScriptの改行文字だからです。

正確\を期すために、エスケープ文字と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"


1
return (input.replace(/([\s"'&+ \ / \\ <> \ u2028 \ u2029 \ u0000])/ g、(match、p1)=> {return \\u${p1.codePointAt(0).toString(16).padStart(4, 0)}; })); `
Denis Giffeler 2017

14

あなたがそれを行うことができます別の方法は-内部の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>

1
JSONの場合、スクリプトタイプ「application / json」を使用します。また、長期的には、オブジェクトとしてトップレベルにするのも良いことです。
OIS、

1
これはオペレーションの質問に直接答えるものではありませんが、それでも私には非常に役に立ちました。私が保存しているデータは、特定の要素ではなくページ全体に適用されるため、要素の属性は実際には機能しません(body要素のように配置しない限り、特に私にとっては少し不自然に思えます)データが大きくなる場合があります)。<script type="application/json" id="MyData"></script>作品に完璧に収納。次に、ActiveWAFL / DblEjを使用して、次のコマンドで検索できますdocument.GetData("#MyData")
エヴァンデラクルーズ

2
この回答には、虚偽/危険な情報が含まれています!スクリプトタイプを変更しても、</ script>タグの検出は変更されません。試してみてください:<script type="application/json" id="MyData"> "abc</script><script>alert()</script>" </script>
ハイパーノット

12

別のオプションは、JSON文字列をbase64エンコードし、JavaScriptで使用する必要がある場合は、atob()関数でデコードすることです。

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

をありがとうatob。私はそれを知らなかった!
Ifedi Okonkwo 2016

3
注意-JSONに非ラテン文字が含まれている場合は機能しません。
Realexer 2016

5

あなたは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());

出力

名:ジェイソン姓:モンテローソ

これを確認してください:http : //learn.knockoutjs.com/


2

ここで空想は何もありません。PHPから、JSON文字列を実行しhtmlspecialcharsて、特殊文字がHTMLとして解釈されないようにします。JavaScriptから、エスケープは必要ありません。属性を設定するだけでよいのです。


2

単純なJSONオブジェクトの場合、以下のコードが機能します。

エンコード:

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

デコード:

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

1

あなたができることはこのようにあなたの要素の周りにcdataを使うことです

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

ここで、mydataは生のJSON文字列です。これがあなたと他の人を助けることを願っています。


このソリューションはどのように機能しますか?">mydataに何かを保存したい場合はどうなりますか?
Martin Pecka 14

1
文字列に「]]>」が含まれる場合
Dobes Vandermeer

1

使用できるもう1つの考えは、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>";
?>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.