List of json - Baldanders.info
tag:Baldanders.info,2019-02-19:/tags
2019-02-19T22:54:05+09:00
バルトアンデルスは連続的な怪物,時間の怪物である。(ホルヘ・ルイス・ボルヘス 『幻獣辞典』より)
https://baldanders.info/images/avatar.jpg
https://baldanders.info/images/avatar.jpg
JSON 形式で Feed を出力する
tag:Baldanders.info,2019-02-19:/hugo/feed-with-json-format/
2019-02-19T13:54:05+00:00
2019-02-19T13:54:05+00:00
Hugo では JSON 形式のファイルも出力できる。
Spiegel
/profile/
<p>今回も小ネタ。</p>
<p>サイトの feed は RSS や Atom といった XML 形式を使うのが普通だが,他サイトの連携を考えるなら JSON 形式で出力できれば色々と便利そうである。
<a href="https://gohugo.io/" title="The world’s fastest framework for building websites | Hugo">Hugo</a> では JSON 形式のファイルも出力できる。</p>
<h2 id="json-形式のファイルを出力するよう設定する">JSON 形式のファイルを出力するよう設定する。</h2>
<p>まずは JSON 形式のファイルを出力できるよう設定ファイル(<code>config.toml</code> など)に以下の記述を追加する。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">outputs</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"> <span class="nx">home</span> <span class="p">=</span> <span class="p">[</span><span class="s2">"HTML"</span><span class="p">,</span> <span class="s2">"RSS"</span><span class="p">,</span> <span class="s2">"JSON"</span><span class="p">]</span>
</span></span></code></pre></div><p>これでサイトのルートディレクトリに <code>index.html</code>, <code>index.xml</code>, そして <code>index.json</code> ファイルを出力できるようになった。</p>
<h2 id="json-ファイルのテンプレートを作成する">JSON ファイルのテンプレートを作成する</h2>
<p>テンプレートファイルを格納する <code>layouts/</code> フォルダの直下または <code>layouts/_default/</code> フォルダに <code>index.json</code> または <code>home.json</code> ファイルを作成する。
中身は例えばこんな感じ。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">{
</span></span><span class="line"><span class="cl"> "title": {{ .Site.Title | jsonify }},
</span></span><span class="line"><span class="cl"> "url": {{ .Permalink | jsonify }},{{ with .OutputFormats.Get "RSS" }}
</span></span><span class="line"><span class="cl"> "feed": {{ .Permalink | jsonify }},{{ end }}
</span></span><span class="line"><span class="cl"> "entry": [{{ range $i, $v := first 3 .Data.Pages }}{{ if ne $i 0 }},{{ end }}{{ with $v }}
</span></span><span class="line"><span class="cl"> {
</span></span><span class="line"><span class="cl"> "title": {{ .Title | jsonify }},{{ with .Section }}
</span></span><span class="line"><span class="cl"> "section": {{ . | jsonify }},{{ end }}{{ with .Description }}
</span></span><span class="line"><span class="cl"> "description": {{ . | jsonify }},{{ end }}
</span></span><span class="line"><span class="cl"> "url": {{ .Permalink | jsonify }},
</span></span><span class="line"><span class="cl"> "published": {{ .Date.UTC.Format "2006-01-02T15:04:05-07:00" | jsonify }},
</span></span><span class="line"><span class="cl"> "update": {{ .Lastmod.UTC.Format "2006-01-02T15:04:05-07:00" | jsonify }}
</span></span><span class="line"><span class="cl"> }{{ end }}{{ end }}
</span></span><span class="line"><span class="cl"> ]
</span></span><span class="line"><span class="cl">}
</span></span></code></pre></div><p>これでコンパイルを行うと以下のような内容で <code>index.json</code> ファイルが出力される。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"title"</span><span class="p">:</span> <span class="s2">"text.Baldanders.info"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"url"</span><span class="p">:</span> <span class="s2">"https://text.baldanders.info/"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"feed"</span><span class="p">:</span> <span class="s2">"https://text.baldanders.info/index.xml"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"entry"</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"title"</span><span class="p">:</span> <span class="s2">"“Article 13” に関するブックマーク"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"section"</span><span class="p">:</span> <span class="s2">"remark"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"description"</span><span class="p">:</span> <span class="s2">"英語不得手の私としては難儀していたが,ようやく日本語の記事を見かけるようになった。"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"url"</span><span class="p">:</span> <span class="s2">"https://text.baldanders.info/remark/2019/02/bookmarks-for-article-13/"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"published"</span><span class="p">:</span> <span class="s2">"2019-02-19T13:04:51+00:00"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"update"</span><span class="p">:</span> <span class="s2">"2019-02-19T13:05:49+00:00"</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"title"</span><span class="p">:</span> <span class="s2">"2019-02-17 のブックマーク"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"section"</span><span class="p">:</span> <span class="s2">"bookmarks"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"description"</span><span class="p">:</span> <span class="s2">"「火星ローバー「オポチュニティ」ミッション終了、15年の活動に幕」他"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"url"</span><span class="p">:</span> <span class="s2">"https://text.baldanders.info/bookmarks/2019/02/17-bookmarks/"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"published"</span><span class="p">:</span> <span class="s2">"2019-02-17T12:25:23+00:00"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"update"</span><span class="p">:</span> <span class="s2">"2019-02-17T12:25:48+00:00"</span>
</span></span><span class="line"><span class="cl"> <span class="p">},</span>
</span></span><span class="line"><span class="cl"> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"title"</span><span class="p">:</span> <span class="s2">"Hugo で Git 情報を取得する"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"section"</span><span class="p">:</span> <span class="s2">"hugo"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"description"</span><span class="p">:</span> <span class="s2">"Hugo の環境を git で管理している場合はコミット情報等をテンプレートに組み込むことができる。"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"author"</span><span class="p">:</span> <span class="s2">"Spiegel"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"license"</span><span class="p">:</span> <span class="s2">"https://creativecommons.org/licenses/by-sa/4.0/"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"url"</span><span class="p">:</span> <span class="s2">"https://text.baldanders.info/hugo/gitinfo/"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"published"</span><span class="p">:</span> <span class="s2">"2019-02-16T13:15:35+00:00"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="nt">"update"</span><span class="p">:</span> <span class="s2">"2019-02-16T13:20:26+00:00"</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><a href="https://gohugo.io/" title="The world’s fastest framework for building websites | Hugo">Hugo</a> では出力ファイルについてかなり細かく制御することが出来るが,今回はこのくらいにしておこう(笑) そのうち詳しい記事を書くこともあるかも知れない。</p>
<h2 id="ブックマーク">ブックマーク</h2>
<ul>
<li><a href="https://gohugo.io/templates/output-formats/">Custom Output Formats | Hugo</a></li>
<li><a href="https://github.com/hugojapan/hugoDocs">GitHub - hugojapan/hugoDocs: Hugo 日本語ドキュメント</a></li>
</ul>
Twitter Badge を貼ってみる
tag:Baldanders.info,2007-04-12:/blog/000315/
2007-04-12T09:00:00+00:00
2007-04-12T09:00:00+00:00
トップページに Twitter Badge を貼ってみる。
Spiegel
/profile/
<p>
トップページに <a href="http://twitter.com/account/badge">Twitter Badge</a> を貼ってみる。
最初は Flash Badge にしてたんだけど,
デザインがイマイチ。
なので,
地味に最新の「さえずり」のみを JavaScript で取得して表示するようにしてみた。
</p><p>
<a href="http://twitter.com/account/badge">Twitter Badge</a> に載っている JavaScript コードを見ると,
以下の URL で JSONP 形式のデータが取れるらしい。
</p><blockquote>
<pre>http://www.twitter.com/statuses/user_timeline/<em>4104801</em>.json?callback=twitterCallback&count=1</pre>
</blockquote><p>
<em>4104801</em> の部分はユーザごとに値が違うので注意。
callback はコールバック関数を,
count は取得するデータの数を指定できるようだ。
サンプルでは単純に JSONP データをインクルードしてるようだけど,
それじゃあ面白くないので,
<a href="https://baldanders.info/blog/000222/">「入門 JSON 3 -- JSONP とコールバック関数」</a>
で紹介した JSONscriptRequest クラスを使ってみる。
</p><blockquote>
<pre><script type="text/javascript" src="/js/jsr_class.js"></script>
<div>
<p><span id="mytwitter"></span></p>
</div>
<script type="text/javascript">
var myId = "4104801";
var oTwitter = new JSONscriptRequest("http://www.twitter.com/statuses/user_timeline/" + myId + ".json?callback=twitterCallback&count=1");
oTwitter.buildScriptTag();
oTwitter.addScriptTag();
function twitterCallback(data) {
var span = "<a href=\"http://twitter.com/" + data[0].user.screen_name + "\">Recent twitter</a> » " + data[0].text;
document.getElementById("mytwitter").innerHTML = span;
oTwitter.removeScriptTag();
}
</script></pre>
</blockquote><p>
myId の値をユーザごとに書き換えればほぼそのまま使えるはず。
まぁ HTML の整形は人それぞれだと思うけど。
</p><p>
あっ,
あと個別ページに <a href="http://twitthis.com/">TwitThis</a> ボタンもつけてみた。
よろしければネタ振り用にご利用ください。
</p>
入門 JSON 3 -- JSONP とコールバック関数
tag:Baldanders.info,2006-08-30:/blog/000222/
2006-08-30T14:12:07+00:00
2006-08-30T14:12:07+00:00
入門 JSON 3 -- JSONP とコールバック関数
Spiegel
/profile/
<p>
最近 JSONP というのが話題になっているようですので,
ここで簡単に紹介します。
</p><p>
JSONP (JSON with Padding)というのは JSON のデータフォーマットにちょっとした記述を加えて <a href="https://baldanders.info/blog/000176/">JavaScript</a> の関数として呼び出せるようにしたものです。
JSONP については以下の記事に簡単な説明があります。(<a href="http://hail2u.net/blog/coding/jsonp.html">多分この記事が初出だろうという話</a>です)
</p><ul>
<li><a href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/">Remote JSON - JSONP</a></li>
</ul>
<div id="a000222more"><div id="more">
<p>
例えば以下のような JSON データがあるとします。
</p><figure>
<pre><code>{ "name" : "Yasuhiro ARAKAWA" }</code></pre>
</figure><p>
JSONP ではこのデータに記述を加えて JavaScript 関数のようにしたものです。
分かりにくいですね。
具体的にはこのように記述します。
</p><figure>
<pre><code>callback( { "name" : "Yasuhiro ARAKAWA" } );</code></pre>
</figure><p>
"callback" の部分は関数の名前として使えるものなら何でもいいです。
例えば
</p><figure>
<pre><code>funclist[1234]( { "name" : "Yasuhiro ARAKAWA" } );</code></pre>
</figure><p>
でも構いません。
何でこんなことをするかというと,
JavaScript で他ドメインの JSON データを非同期で読み込むことができるからです。
</p><p>
以前<a href="https://baldanders.info/blog/000171/">「入門 JSON」</a>にて,
JavaScript でリモートのデータを呼び込む際に2通りの方法があると説明しました。
ひとつは XMLHttpRequest クラスを使う方法,
もうひとつは JavaScript ソースとしてインクルードする方法です。
「クロスドメインの制約」からXMLHttpRequest を使う方法では読込先が他ドメインの場合は使えません。
そこでデータを JSONP の形式にして JavaScript のソースとしてインクルードしてしまうわけです。
また JSONP は関数呼び出しの形式になっているので,
その関数の処理を別に記述することでコールバック関数のように機能します。
</p><p>
JSONP を上手く処理するためのクラスを公開しておられる方もいます。
</p><ul>
<li><a href="http://www.xml.com/pub/a/2005/12/21/json-dynamic-script-tag.html">JSON and the Dynamic Script Tag: Easy, XML-less Web Services for JavaScript</a></li>
</ul><p></p>
この記事で公開している jsr_class.js というソースファイルがそれです。
このソースでは JSONscriptRequest というクラスが定義されています。
早速使ってみましょう。
実はソーシャル・ブックマーク・サービスの <a href="http://del.icio.us/">del.icio.us</a> では JSONP 形式のフィードも提供しています。
例えば私のブックマーク(<a href="http://del.icio.us/spiegel">http://del.icio.us/spiegel</a>)を JSONP 形式で取得するには以下のように URI を指定します。
<p></p><ul>
<li><a href="http://del.icio.us/feeds/json/spiegel?callback=hundler">http://del.icio.us/feeds/json/<em>spiegel</em>?callback=<em>hundler</em></a></li>
</ul><p></p>
<em>spiegel</em> の部分には del.icio.us のユーザ名が入ります。
また <em>hundler</em> の部分には任意の関数名を指定します。
ここで指定した関数がコールバック関数となります。
試してみると分かりますが,
この URI を呼び出すと以下のような文字列が得られます。
<p></p><figure>
<pre><code><em>hundler</em>([ ... ])</code></pre>
</figure><p>
<code>[ ... ]</code> の部分が JSON 形式の配列データになっているわけです。
</p><p>
ところで余談ですが,
ついに JSON フォーマットが <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC4627</a> として正式な仕様になりました。
メディアタイプも application/json と決まりました。
以前<a href="https://baldanders.info/blog/000174/">「入門 JSON 2」</a>で
「JSON ではこのオブジェクトがデータの基本になっています」
と書きましたが,
<a href="http://www.ietf.org/rfc/rfc4627.txt">RFC4627</a> によると
</p><blockquote>
"A JSON text is a serialized object or array."
</blockquote><p>
とあり,
オブジェクト(=連想配列)と配列のどちらでもいいようです。
</p><p>
では JSONP データと JSONscriptRequest クラスを使ってブックマークのリストを作ってみましょう。
</p><figure>
<pre><code><script type="text/javascript" src="/js/jsr_class.js"></script>
<div id="bookmark"></div>
<script type="text/javascript">
var oJsr = new JSONscriptRequest('http://del.icio.us/feeds/json/spiegel?callback=hundler');
oJsr.buildScriptTag();
oJsr.addScriptTag();
<p>function hundler(data) {
var ul = document.createElement('ul');
for (var i=0, post; post = data[i]; i++) {
var li = document.createElement('li');
var a = document.createElement('a');
a.setAttribute('href', post.u);
a.appendChild(document.createTextNode(post.d));
li.appendChild(a);
ul.appendChild(li);
}
document.getElementById('bookmark').appendChild(ul);
oJsr.removeScriptTag();
}
</script></code></pre></p>
</figure>
<p>(2020−07−31追記:実行結果表示は削除した)</p>
<p>
JSONscriptRequest クラスには3つのメソッドがあります。
1つ目は buildScriptTag メソッド。
コンストラクタ引数の URI から script 要素(タグ)を生成します。
2つ目は addScriptTag メソッドで,
buildScriptTag で生成した script 要素を HTML の head 要素内に追加します。
簡単に言うと addScriptTag メソッドを呼び出した時点で URI 先のデータが読み込まれコールバック関数が実行されます。
3つ目の removeScriptTag メソッドは生成した script 要素を HTML の head 要素から削除します。
後始末係ですね。
</p><p>
JSONP や JSONscriptRequest クラスは JSON データの使い勝手を向上させますが,
<a href="https://baldanders.info/blog/000171/">「入門 JSON」</a>でも指摘した通り,
この方法は常にセキュリティ上のリスクが伴うことを忘れないでください。
とくに JSONP はサーバ側の実装によっては重大な XSS 脆弱性を抱える可能性があります。
この記事が参考になれば幸いです。
</p><p>
参考:
</p><ul>
<li><a href="http://www.ietf.org/rfc/rfc4627.txt">RFC4627 -- The application/json Media Type for JavaScript Object Notation (JSON)</a></li>
<li><a href="http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/">Remote JSON - JSONP</a></li>
<li><a href="http://www.xml.com/pub/a/2005/12/21/json-dynamic-script-tag.html">JSON and the Dynamic Script Tag: Easy, XML-less Web Services for JavaScript</a></li>
<li><a href="http://hail2u.net/blog/coding/jsonscriptrequest.html">JSONScriptRequest</a></li>
<li><a href="http://hail2u.net/blog/coding/jsonp.html">JSONP</a></li>
<li><a href="http://d.hatena.ne.jp/aql/20060807/1154948646">JSONPを用いてクロスドメインで情報を取得する</a></li>
<li><a href="http://d.hatena.ne.jp/shinichitomita/20060825/1156504036">ブラウザからJSONで呼び出せるサービス一覧</a></li>
</ul>
</div></div>
入門 JSON 2
tag:Baldanders.info,2006-03-08:/blog/000174/
2006-03-08T12:48:23+00:00
2006-03-08T12:48:23+00:00
入門 JSON 2
Spiegel
/profile/
<p>
<a href="https://baldanders.info/blog/000171/">「入門 JSON」</a>が微妙に評判がいいみたいなので,
今回はもう少し踏み込んだ内容を書いてみたいと思います。
前回では JSON のデータフォーマットについて曖昧な表現や説明のまま流していますが,
ここではもう少し厳密に見ていきます。
またもや長文です。
ご注意を。
なお,
この記事は<a href="http://www.json.org/">「Introducing JSON」</a>(<a href="http://d.hatena.ne.jp/brazil/20050915/1126709945">日本語訳</a>)と併せてご覧いただくことをお奨めします。
</p>
<div id="a000174more"><div id="more">
<p>
前回は JSON のデータ型について連想配列(<code><em>members</em></code>)と配列(<code><em>array</em></code>)の2つがあると説明しました。
しかし実際にはもうひとつオブジェクト(<code><em>object</em></code>)という型があります。
実は JSON ではこのオブジェクトがデータの基本になっています。
(説明が長くなるので前回はこの部分についてワザと端折りました)
</p><p>
オブジェクトは以下に示すようにブレス記号で囲んだ表現になります。
</p><blockquote>
<pre><code>{ }
{ <em>members</em> }</code></pre>
</blockquote><p>
ここで注意すべきなのはオブジェクトの内容は(空でないなら)必ず連想配列でなければならないことです。
例えば,
以下のようなオブジェクト-配列表現は許容されません。
</p><blockquote>
<pre><code>{
[ "element1", "element2" ]
}</code></pre>
</blockquote><p>
またこのような表現も(一見正しいように見えますが)間違いです。
</p><blockquote>
<pre><code>{
{ "name1" : "value1" },
{ "name2" : "value2" }
}</code></pre>
</blockquote><p>
オブジェクトを示すブレス記号は単なる区切りではないということです。
</p><p>
次に連想配列ですが,
以下に示すような「名前:値」表現になります。
</p><blockquote>
<pre><code><em>string</em> : <em>value</em>
<em>members</em>, <em>string</em> : <em>value</em></code></pre>
</blockquote><p>
名前と値(<code><em>value</em></code>)の間はコロン記号で区切ります。
また連想配列を列挙する場合はカンマ記号で区切ります。
名前は必ず文字列(<code><em>string</em></code>)でなければなりません(文字列の形式については後述)。
そして配列は以下に示すように配列要素(<code><em>elements</em></code>)をブラケット記号で囲んだ表現になります。
</p><blockquote>
<pre><code>[ <em>elements</em> ]</code></pre>
</blockquote><p>
配列要素はひとつ以上の値をカンマ記号を区切り文字として列挙します。
</p><blockquote>
<pre><code><em>value</em>
<em>elements</em>, <em>value</em></code></pre>
</blockquote><p>
連想配列にしろ配列にしろ要素を列挙する場合はカンマ記号に注意してください。
例えば以下に示すように最後の要素の後にカンマ記号を入れるのは間違いです。
</p><blockquote>
<pre><code>{ "array" : [
"element1",
"element2",
] }</code></pre>
</blockquote><p>
連想配列および配列の値として許容できる形式は以下の通りです。
</p><ul>
<li>文字列</li>
<li>数値(<code><em>number</em></code>)</li>
<li>オブジェクト</li>
<li>配列</li>
<li>true, false</li>
<li>null</li>
</ul><p>
例えば配列要素として以下のように連想配列を直接入れることはできません。
</p><blockquote>
<pre><code>{ "array" : [
"name1" : "value1",
"name2" : "value2"
] }</code></pre>
</blockquote><p>
連想配列の要素を配列に入れる場合は,
いったんオブジェクトにする必要があります。
(以下は連想配列の要素を個別にオブジェクトとする場合)
</p><blockquote>
<pre><code>{ "array" : [
{ "name1" : "value1" },
{ "name2" : "value2" }
] }</code></pre>
</blockquote><p>
文字列は文字(<code><em>char</em></code>)の列(<code><em>chars</em></code>)をダブルクォーテーション記号で囲んだ形式です。
</p><blockquote>
<pre><code>""
"<em>chars</em>"</code></pre>
</blockquote><p>
文字列として使える文字は通常の UNICODE 文字(ダブルクォーテーション記号およびバックスラッシュ記号(<code>\</code>)を除く)の他,
バックスラッシュ記号からはじまるエスケープシーケンスが使えます。
利用可能なエスケープシーケンスを以下に示します。
C 系のプログラミング言語を扱っている方にはなじみのある表現だと思います。
</p><blockquote><table>
<tbody><tr><td>\"</td> <td>quotation mark</td></tr>
<tr><td>\/</td> <td>solidus</td></tr>
<tr><td>\\</td> <td>reverse solidus</td></tr>
<tr><td>\b</td> <td>backspce</td></tr>
<tr><td>\f</td> <td>form feed</td></tr>
<tr><td>\n</td> <td>newline</td></tr>
<tr><td>\r</td> <td>carriage return</td></tr>
<tr><td>\t</td> <td>holizontal tab</td></tr>
<tr><td>\u<em>four-hex-digits</em></td> <td>charactor code for UNICODE</td></tr>
</tbody></table></blockquote><p>
文字列データにおいて文字コード(厳密には文字エンコーディング)は常に悩みの種ですが,
JSON においては UNICODE のみ許容しています。
したがって他の文字コード(Shift-JIS や EUC-JP など)を採用しているツール・サービスでは文字コードの変換処理も必要になります。
</p><p>
数値は10進数のみ(任意のN進数には対応していません)で,
マイナス表現や指数表現を許容します。
例えば <code>-1.23e+4</code> といった感じです。
<code>+1</code> や <code>001</code> といった表現は許容されません(必ずサプレスします)。
また数式表現も許容されません。
(<a href="https://baldanders.info/blog/000171/">前回</a>紹介した xml2json.cgi は数値の解釈がうまくなく時々変換をしくじります。
私は Perl とか正規表現とかいったものはあまり得意ではないので,
どなたかやってくださらないかなぁ...)
</p><p>
JSON は値としてオブジェクトを許容しているため,
いくらでもデータを入れ子にすることができます。
この部分がデータフォーマットとしての柔軟性に繋がっていて,
XML と同様に従来の RDBMS とはまた違ったデータベース操作を可能にしています。
(いくらでもデータを入れ子にできるというのはリスクでもあります。
データ同士の関連が循環しているような構造のデータベースを JSON に展開するときは注意が必要です)
</p><p>
JSON は Javascript の言語仕様をベースに作られたことは<a href="https://baldanders.info/blog/000171/">前回</a>説明しましたが,
これまで述べたように Javascript に比べると色々と制約が多いと言えます。
しかし実際には JSON は Javascript の eval 関数で簡単にインポートできてしまうため,
Javascript で解釈可能な表現ならば何でも受け入れてしまう可能性があります。
特に問題になりそうなのは値(<code><em>value</em></code>)として関数(<code><em>function</em></code>)が記述されている場合です。
</p><p>
もし JSON データを自前で構文解析して Javascript 表現に変換できるのなら比較的安全に取り扱うことができます。
<a href="http://www.json.org/js.html">「JSON in JavaScript」</a>では JSON.parse をパーサとして使うことを推奨しています。
例えば JSON データ json.txt を Javascript 上でインポートするには以下のようなコードにします。
</p><blockquote>
<pre><code><script type="text/javascript" src="jkl-parsexml.js"></script>
<script type="text/javascript" src="json.js"></script>
<script type="text/javascript">
var url = "json.txt";
var json = new JKL.ParseXML.Text(url);
var text = json.parse();
var data = JSON.parse(text);
</script></code></pre>
</blockquote><p>
json.txt の読み込みには<a href="https://baldanders.info/blog/000171/">前回</a>も紹介した <a href="http://www.kawa.net/works/js/jkl/parsexml.html">JKL.ParseXML</a> ライブラリを利用しています。
このライブラリではクロスドメインの制約を超えられないのでご注意を。
クロスドメインの制約を超えるためには(<a href="https://baldanders.info/blog/000171/">前回</a>紹介した) xml2json.cgi などの CGI を使う必要があります。
</p><p>
さて,
これで JSON について大体のイメージができたのではないでしょうか。
この記事が少しでもお役に立てれば幸いです。
</p>
</div></div>
入門 JSON
tag:Baldanders.info,2006-03-03:/blog/000171/
2006-03-03T08:32:41+00:00
2006-03-03T08:32:41+00:00
入門 JSON
Spiegel
/profile/
<p>
ここではあまりプログラミングの話はしないのですが(私も今気がついた),
たまにはいいでしょう。
今回は JSON というデータフォーマットのお話です。
めっさ長文です。
ご注意を。
(3/8 追記があります)
</p>
<div id="a000171more"><div id="more">
<p>
最近 <a href="http://www.json.org/">JSON (JavaScript Object Notation)</a>にハマってます。
JSON というのはごく軽量のデータフォーマットで,
Javascript (というより ECMAScript と言うべきかもしれませんが)の言語仕様がベースになっています。
とはいえ,
JSON 自体は Javascript からは独立していますので他の言語(C/C++, Java, C#, Perl, Ruby, Python など)でも問題なく扱うことができます。
JSON は以下の2種類のデータ構造の組み合わせでできています。
(JSON フォーマットの詳しい解説をご所望の方は<a href="https://baldanders.info/blog/000174/">「入門 JSON 2」</a>を参照ください)
</p><ul>
<li>「名前:値」の組み合わせ(連想配列)。組み合わせ自体をひとつの要素として扱うことができます。</li>
<li>要素の順序つきリスト(配列)。リスト全体をひとつの要素として扱うことができます。</li>
</ul><p>
例えば私についての情報を JSON で作成するとしましょう。
まず私の名前は連想配列を使って
</p><blockquote>
<pre><code>{ "name" : "Yasuhiro ARAKAWA" }</code></pre>
</blockquote><p>
といった具合に表現できます
(「名前:値」の名前の部分は必ず文字列である必要があるのでクォーテーションで囲みます。私はここでハマりました)。
ついでにニックネームも追加しましょうか。
データ全体をあらわす名前も付けますしょう。
</p><blockquote>
<pre><code>{
"Person" : {
"name" : "Yasuhiro ARAKAWA",
"nick" : "Spiegel"
}
}</code></pre>
</blockquote><p>
更に最近注目しているサイトなんかも入れてみましょう。
</p><blockquote>
<pre><code>{
"Person" : {
"name" : "Yasuhiro ARAKAWA",
"nick" : "Spiegel",
"interest" : [
{ "title" : "SETI@home", "url" : "http://setiathome.ssl.berkeley.edu/" },
{ "title" : "Flickr", "url" : "https://www.flickr.com/" }
]
}
}</code></pre>
</blockquote><p>
何かに似てきました。
そう FoaF です(というか,似るように要素を追加していったのですが)。
JSON の記法は RDF の Turtle に似ているそうで,
RDF への応用を考えている方もいらっしゃいます。
</p><ul>
<li><a href="http://www.kanzaki.com/memo/2006/02/21-1">JSONではじめるRDF/Turtle</a></li>
<li><a href="http://www.kanzaki.com/memo/2006/02/21-2">JSONではじめるRDF/Turtle(2) - 名前空間</a></li>
<li><a href="http://www.kanzaki.com/memo/2006/02/21-3">JSONではじめるRDF/Turtle(3) - 型付ノード</a></li>
</ul><p>
JSON は(成り立ちから考えても当然ですが) Javascript と非常に相性の良いフォーマットです。
JSON のデータを丸ごと Javascript の eval メソッドに通すと構造ごとオブジェクトができてしまいます
(実際にはそのまま eval メソッドに通すのはセキュリティ上危険なので,
<a href="http://www.json.org/js.html">JSON.parse</a> などのパーサを通すことが推奨されています)。
Javasript と相性がいいということは Web ブラウザ(クライアント側)で操作がしやすいということです。
そこで当然 Ajax と組み合わせたアプリケーションが色々と思いつくわけですが,
そうなると XML と JSON との相互変換が重要になってきます。
XML と JSON との相互変換,
特に XML から JSON への変換を行うライブラリは既にネットに色々あるようです。
Javascript で動作するものでは以下のライブラリがいい感じです。
</p><ul>
<li><a href="http://www.kawa.net/works/js/jkl/parsexml.html">JKL.ParseXML - ajax 通信処理ライブラリ</a></li>
</ul><p>
Javascript でリモートのデータを取得するには XMLHttpRequest クラスを使うのですが,
XMLHttpRequest ではセキュリティ上の制約から他所のドメインにアクセスできないようになっています(「クロスドメインの制約」と言います)。
他所のドメインから XML や JSON データを取得するには大きく2つの方法があります。
ひとつは,
いったんサーバ側でデータを取得してからクライアントに渡す方法(CGI などのサーバサイド・スクリプトが必要です)。
もうひとつは Javascript ソースとしてインクルードする方法です。
del.icio.us では <a href="http://del.icio.us/help/json">JSON データのフィード</a>に後者の方法を使っています。
この方法はとても便利なのですが,
JSON データを無条件に受け入れてしまうためセキュリティ上の危険を意識する必要があります。
</p><p>
前者の方法は(サーバ側で適切なパーサを通せば)後者よりもいくらかマシです。
そこで,
前者の方法を試してみることにします。
<a href="http://boinc.berkeley.edu/download.php?xml=1">BOINC が提供しているクライアントのバージョン情報(XML 形式)</a>をサーバ側で取得し,
JSON 形式に変換してクライアントに渡します。
サーバ側のスクリプトには以下を使わせていただきました。
</p><ul>
<li><a href="http://tech.nitoyon.com/javascript/xml2json.html">xml2json.cgi - ドメインを超えてXMLを読みこむ</a></li>
</ul><p>
このスクリプトは Perl の Data::Dumper が JSON の形式に似ていることを利用して効率的に変換を行っています。
ただ,
これをこのまま使うとオープンプロキシのようになってしまうので,
特定 URL の情報のみを取得するように改造しました。
このスクリプトで取得した JSON データを<a href="http://huaa.baldanders.info/">「Club-HUAA サポートページ」</a>で受けてクライアント側で表示します。
クライアント側の Javascript は以下のような感じです。
</p><blockquote>
<pre><code><div id="versiondata">読み込み中...</div><script>
window.onload = function(){
var s = document.getElementsByTagName("head")[0].appendChild(document.createElement("script"));
s.type = "text/javascript";
s.charset = "utf-8";
s.src = "http://huaa.baldanders.info/xml/?type=client";
}
var client = {};
client.onload = function(data){
var src = "<div><table>";
var platform = "";
for (i = 0; i < data.versions.version.length; ++i) {
var item = data.versions.version[i]
if( item.platform != platform ) {
src += "<tr><th colspan=\"4\">" + item.platform + "</th></tr>";
platform = item.platform;
}
src += "<tr>"
src += "<td><a href=\"" + item.url + "\">" + item.description + " " + item.version_num + "</a></td>"
src += "<td>" + item.installer + "</td>"
src += "<td>" + item.size_mb + " MB</td>"
src += "<td>" + item.date + "</td>"
src += "</tr>"
}
src += "</table></div>";
document.getElementById("versiondata").innerHTML = src;
}
</script></code></pre>
</blockquote><p>
結果については<a href="http://huaa.baldanders.info/xml/test2.html">テストページ</a>を参照してください。
CGI パラメータ以外にも若干修正しています。
取得したデータは一定時間キャッシュするようになっているのですが,
キャッシュの時間を10分から6時間に変更しました。
また XMLin で XML データを Perl の内部表現に変換する際に XML のルート要素が欠落する問題があったため,
該当部分を以下のように変更しています。
</p><blockquote>
<pre><code>my $xmlobj = XMLin($res->content);
↓
my $xmlobj = XMLin($res->content, KeepRoot => 1);</code></pre>
</blockquote><p>
最終的なスクリプトを <a href="http://huaa.baldanders.info/xml/xml2json.txt">xml2json.txt</a> に公開しています。
また CGI の機能については<a href="http://huaa.baldanders.info/log/000173.shtml">「JSON 変換サービス」</a>を参考にしてください。
(順次機能を増やしていく予定です)
</p><p>
クライアント側で簡単にデータを操作できるというのはサービスのユーザにとって大きなメリットがあります。
一方でセキュリティ上の問題も見逃せないところです。
これからも JSON に注目していきたいと思います。
</p>
</div></div>