text.json 0.2

text.json 0.2をリリースします。もともとrfc.jsonが標準ライブラリに入るまでのつなぎのつもりでしたが、マッピングを変更できたらうれしいかも、と魔が差してもう少し書いてみることにしました。インストール方法やアーカイブはこちら:

Gauche 0.9.1よりJSONのパーズ/構築を行うrfc.jsonが標準で提供されています。したがって、通常このモジュールをインストールする必要はありません。rfc.jsonで今のところ提供されていない機能(マッピングのカスタマイズ・Pretty-Print)が使いたいという場合、このモジュールが役に立つかもしれません。

マッピングのカスタマイズ

json-readではオブジェクトと配列をそれぞれ連想リストとベクタにマッピングしていましたが、パラメータを使ってこのマッピングを変更できるようになりました。

(use gauche.parameter)

(define text "{\"foo\": 1, \"bar\": [2, 3]}")

;; デフォルトでオブジェクトは連想リストに、配列はベクタにマッピングされる
(let1 alist (json-read text)
  (write alist)                      ; => (("foo" . 1) ("bar" . #(2 3)))
  (print (cdr (assoc "foo" alist)))  ; => 1
  (print (cdr (assoc "bar" alist)))  ; => #(2 3)
 )

;; ハッシュテーブルとリストに変更
(parameterize ((json-object-fn (cut make-hash-table 'string=?))
               (json-array-fn (cut values <list> #f)))
  (let1 ht (json-read text)
    (write ht)                         ; => #<hash-table string=? 0x1900280>
    (newline)
    (print (hash-table-get ht "foo"))  ; => 1
    (print (hash-table-get ht "bar"))  ; => (2 3)
   ))

読み込み時のマッピングjson-object-fn, json-array-fn パラメータに引数を取らない手続きを与えることで変更できます。

一方SchemeオブジェクトをJSONへ書き出す場合、(is-a? obj )が真となるobjはオブジェクトに、
(is-a? obj )が真となるオブジェクトは配列と見なされます。しかし、いくつかの例外があります。

  • 文字列()はのサブクラスですが、(JSONの)文字列となります。
  • リスト()ものサブクラスですが、デフォルトでは連想リストと見なされ、オブジェクトとして書き出されます。この挙動はlist-as-json-arrayパラメータに真の値を与えることで変更することができます。

詳しくはREADMEを見てみてください。

Pretty Print

新しい手続きjson-write*を追加しました。json-writeと同様にSchemeオブジェクトをJSONとして出力しますが、出力にはインデントと改行が補われます。インデントに使用される文字列はjson-indent-stringパラメータで変更可能です。

gosh> (define obj '(("foo" . 1) ("bar" . #(2 3))))
obj
gosh> (use text.json)
#<undef>
gosh> (json-write obj)
{"foo":1,"bar":[2,3]}#<undef>
gosh> (json-write* obj)
{
  "foo": 1,
  "bar": [
    2,
    3
  ]
}#<undef>
gosh> (use gauche.parameter)
#<undef>
gosh> (parameterize ((json-indent-string "-->")) (json-write* obj))
{
-->"foo": 1,
-->"bar": [
-->-->2,
-->-->3
-->]
}#<undef>


というわけで、気が向いたら使ってみてください!