はいどうも~。エンジニアの吉田だよ。


今日は、気分転換に口語調モードで綴ってみるね。


ここ最近の仕事は、ほとんどの案件で当たり前のようにJSONを使っているんだけど、

おバカなせいかしら、「そういえば、JSONの仕様ってどんなだったかしら?」なんて風に

すぐに忘れてしまうのよ。


だから、メモと復習も兼ねてJSONの仕様をRFCで再確認してみるわ。


JSONの仕様はIETF (Internet Engineering Task Force) のサイトで

RFC (Request for Comments) として公開されているから、困ったときは

巷のWebサイトで調べるよりも、RFCを確認すると間違いないの。


二次情報より一次情報を調べるということはとても大事なことなのよ。


というわけで、早速JSONのRFCをユルい感じで見てみるわね。



RFC4627

JSONの仕様はRFC4627として公開されているの。

The application/json Media Type for JavaScript Object Notation (JSON)
http://www.ietf.org/rfc/rfc4627

右上には日付が書かれていて、2006年7月からRFCが公開されていることがわかるわね。


Abstract

大概のRFCは最初にAbstractという項で概要が説明されているわ。
ユルい感じで訳してみると、こんな感じかしら?

「JSONは軽量でテキストベースでECMAScriptに依存したデータ交換フォーマットなの。
 構造化されたデータのフォーマットをシンプルに定義しているのよ。」


Introduction

IntroductionにはJSONのデータ仕様がふんわりと説明されているの。

「JSONには4つのプリミティブタイプと、2つの構造体タイプが用意されているわ。
 プリミティブタイプは string と number と boolean と null の4つ。
 構造体タイプは object と array の2つ、たったこれだけなの。シンプルでしょ?」

「string は、0文字か、1文字以上のUnicode文字が続いたもの。」

「object は、"名前"と"値"がペアになっているコレクションよ。カラッポの場合もあるわ。
 "値"には、string, number, boolean, null, object, array を使うことができるの。」

「arrayは、"値"が順序付きで格納されているコレクションよ。カラッポの場合もあるわ。」

「object と array はJavaScriptの文法をそのまま採用しているのよ。」

「JSON仕様は、小さくて、持ち運びやすくて、テキストベースで、JavaScriptの
 サブセットになるように設計されているわ。」

といった感じかしら?


JSON Grammar

JSON Grammerでは、その名の通りJSONの文法が説明されているの。


「JSONは object か array のどちらかなのよ」


「構造体タイプには次の6つの文字を使うことが決められているわ。」

 ・arrayの開始 = ws %x5B ws  ← [ (左角括弧)

 ・objectの開始 = ws %x7B ws  ← { (左波括弧)

 ・arrayの終了 = ws %x5D ws  ← ] (右角括弧)

 ・object終了 = ws %x7D ws  ← } (右波括弧)

 ・名前の区切り = ws %x3A ws  ← : (コロン)

 ・値の区切り = ws %x2C ws  ← , (カンマ)


「wsっていうのはホワイトスペースのことよ。半角スペース、水平タブ、改行文字を使うことが許されているわ。」


Values

「さっきと同じことを繰り返すけれど、値には object, array, number, string か、

 false, null, true の3つのリテラルを使うことができるのよ。シンプルでしょ?」


Objects

「object は次のような決まりになっているの。中身がカラッポの場合もOKよ。」

 0件: {}

 1件: { string : value }

 複数件: { string : value, string : value }


Arrays

「array は次のような決まりになっているの。これも中身カラッポOKよ。」

 0件: []

 1件: [ value ]

 複数件: [ value, value ]


Numbers

「number は整数、負数、少数の値を使うことができるわ。」

「8進数や16進数表記は許可されていないわ。」

「先頭のゼロ埋めも許可されていないわ。」

「指数表記はOKよ。指数部は e か E で区切る必要があるわ。」

「POSITIVE_INFINITY や NEGATIVE_INFINITY や NaN は許可されていないわ。」


Strings

「string はダブルクォーテーション(")で囲う必要があるわ。」

「ただし、次の文字はエスケープする必要があるのよ。」

 " (ダブルクォーテーション)

 \ (バックスラッシュ)

 / (スラッシュ)

 \b (バックスペース)

 \f (フォームフィード)

 \n (ラインフィード)

 \r (キャリッジリターン)

 \t (水平タブ)

 \uXXXX (Unicodeエスケープとみなす文字)


Encoding

「JSONは基本的にUTF-8エンコーディングを採用しているわ」


Parsers

「JSONパーサーはJSON文法に準拠したテキストを受け入れる必要があるわ。」

「あと、実装によっては、テキストの長さや、文字列の長さや、ネスト数に制約が

 設けられているかもしれないわよ。」


Generators

「JSONを生成するにはJSONの文法に準拠している必要があるわよ。」


IANA Considerations

「JSONのMIMEタイプは application/json なのよ。」


Security Considerations

「JSONは、JavaScript内でJSONテキストからオブジェクトに変換するときに、

 eval()で変換すると思うんだけど、そのときに正しいJSON形式かどうかを

 チェックした方がいいわよ。」

「こんな感じの正規表現で簡単にチェックできるから、アタシのを参考にするといいわ。」

var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
       text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
    eval('(' + text + ')');



といった感じでしょうか。

※口語調で綴るつもりのものが、なんだかオネエっぽくなってしまいました。。


改めてRFCを読んでみると、NumberにはNaNとかInfinity使えないとか、

当然なようなことも明確化されていることに、ちょっと新鮮さを感じました。


仕様をきちんと説明するには、当たり前のことも丁寧に書かねばなりませんね。。



そうそう、JSONを出力する場合の補足を1つ。ブラウザからの直接アクセスによる

XSS脆弱性を防ぐため、 "<" と ">" は、それぞれ \u003C と \u003E に

Unicodeエスケープしてから出力するよう心がけましょう。


デワデワン。