as3corelib の JSON.decode() をいい加減な JSON に対応させる

JSON は手軽に書けていいのですが、仕様がちょっと厳密すぎるところもあるので緩い JSON で書きたくなる。

JSON の仕様で個人的に面倒だと思うのは次の3つ。

  1. object や array の最後に , があるとエラーになる
  2. object のキーは文字列じゃないといけない
  3. 0.3.3 と書くとエラーになる

たとえば、次のような JSON はパースエラーとなる。

{
    a: .3, 
    b: .4, 
    c: .9, 
}

本当はこうすべき。

{
    // a → "a"
    "a": 0.3, // .3 → 0.3
    "b": 0.4, 
    "c": 0.9  // カンマを削った
}

オレオレなプロジェクトで JSON を手書きするときには、この3つの制限を緩和してあげたくなる。json.org の仕様には違反しちゃうけど、書きやすさを優先で GO!!!

そこで、ActionScript の定番 JSON パーサーである as3corelib の .92.1 に手を入れてみた。

たとえば、配列末尾のカンマを許容するには com/adobe/serialization/json/JSONDecoder.as の parseArray() 関数に次のように手を入れた。

     } else if ( token.type == JSONTokenType.COMMA ) {
         // move past the comma and read another value
         nextToken();
+
+        // allow trailing comma.
+        if ( token.type == JSONTokenType.RIGHT_BRACKET ) {
+            return a;
+        }
     } else {

カンマだったときに次が ] だったら、配列を返すようにする。

こんな感じで、ごにょごにょといじっていく。

「2. object のキーは文字列じゃないといけない」については、そもそも JSON の仕様に identifier がないので、ECMAScript の仕様を参考にしつつ、JSONTokenizer.as に手を入れていった。本当はキー名として日本語などの Unicode 文字も許可しなきゃいけないんだけど、めんどくさいので

/^[a-z_$][a-z_$0-9]*$/

を許可するキー名の条件とした。

完成品のソースはここにおいてる:

ここに置いてるやつを使えば

{
    a: .3, 
    b: .4, 
    c: .9, 
}

がパースエラーにならない。やったね。