GaucheでJSONを送信したい
と思ったので、SchemeでJSONの実装がないか適当に検索したら、なんかPackratとかいう構文解析ライブラリを利用したややこしい実装が出てきたが、Gaucheのモジュールとかないし、解析機能要らんし、ちょっとJSON作って送信したいだけなのにソース読むとか面倒臭いので、自分で欲しい機能だけ適当に作ってしまうことにする。
さしあたり、SXMLみたいにJSONを組み立てて、べたテキストか何かにしてcgi-mainで飛ばせるようにしたいわけだ。
とりあえずJSONの配列はそのままリストにして、"ラベル":値 みたいなのはドット対で表し、そのリストでオブジェクトを表すことにすると、適当に文字列に変換する関数が作れた。
(define (string-quote str) (string-append "\"" str "\"")) (define (json-array ls) (letrec ( (json-array-in (lambda (ls result) (if (null? ls) result (json-array-in (cdr ls) (string-append result (json-value (car ls)) (if (null? (cdr ls)) "" ",") )) )) )) (string-append "[" (json-array-in ls "") "]")) ) (define (json-value ls) (cond ( (string? ls) (string-quote ls)) ( (number? ls) (number->string ls)) ( (boolean? ls) (if ls "true" "false")) ( (null? ls) "null") ( (list? ls) (if (and (pair? (car ls)) (not (null? (car ls))) (string? (caar ls))) (json-object ls) (json-array ls) ) ) (else "null")) ) (define (json-object ls) (letrec ((json-object-in (lambda (ls result) (if (null? ls) result (json-object-in (cdr ls) (string-append result (string-quote (caar ls)) ":" (json-value (cdar ls)) (if (null? (cdr ls)) "" ",") )) )) )) (string-append "{" (json-object-in ls "") "}")) )
ネストが無駄に深いな…。多分、R5RS準拠なら動く?
適当に例を挙げると、
(json-value '(("a" . (("aa" . "test") ("ab" . "test1")) ) ("b" . -1222) ))
これがこんな文字列になる。ドットの前後には空白を入れましょう。
{"a":{"aa":"test","ab","test1"},"b":-1222}
エラー処理とかあんまり考えてへんけど、さしあたりの用途にはこれで十分。
あれ、SXMLをJSONに変換したほうが良かったんか…?