Release 0.0.4 · gongo/json-reformat · GitHub
修正内容
v0.0.3 までは、空のハッシュに対して json-reformat-region
とかを仕掛けると、
下記のように null になってしまう という 仕様 でした。
{"foo": {}} // ↓↓↓ { "foo": null }
v0.0.4 からは、ちゃんと空のハッシュのまま整形できるようになりました。
{"foo": {}} // ↓↓↓ { "foo": { } }
空のハッシュであれば "foo": { }
という感じで改行入らない方がいいかもしれませんね。
いつか考えます。
今回の内容を仕様としていた理由
json-reformat.el では、JSON テキストのパースを (json-read)
で行っています。
;; $ cat foo.json ;; { ;; "foo": 3, ;; "bar": "pizza" ;; } (dolist (type '(plist alist hash-table)) (let ((json-object-type type)) (with-temp-buffer (insert-file-contents "foo.json") (json-read)))) ;; => (:bar "pizza" :foo 3) ;; => ((bar . "pizza") (foo . 3)) ;; => #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data ("foo" 3 "bar" "pizza" ...))
このように alist
plist
hash-table
の中の好きな形でパースした結果を受け取れます。
v0.0.3 までは plist
で実装していたのですが、この時問題となるのが、前述の 空のハッシュ です。
;; $ cat foo.json ;; { ;; "foo": {}, ;; "bar": null ;; } (let ((json-object-type 'plist)) (with-temp-buffer (insert-file-contents "foo.json") (json-read))) ;; => (:bar nil :foo nil)
このように 空のハッシュも null もパースすると nil になってしまう ということで、
受け取った側としては「どっちかわからんから {}
に直すこともできねーなー」となって
最終的に「これは仕様ですわー」みたいな感じにしていました。
光明
そんなことを Tweet してみたところ、 @kiwanami さんから以下の reply をいただきました。
@gongoZ デフォルトだとObject -> alistなので、(foo . ()) -> (foo . nil) -> () で、JSONとS式の変換上仕方がないかなと思ったりします。json-object-type を hash-table にすると往復できるかも。
— kiwanami (@kiwanami) 2015, 7月 23
なるほど hash-table
と思って実際に試してみたところ
;; $ cat foo.json ;; { ;; "foo": {} ;; } ;; $ cat bar.json ;; { ;; "bar": null ;; } (let ((json-object-type 'hash-table)) (dolist (filename '("foo.json" "bar.json")) (with-temp-buffer (insert-file-contents filename) (json-read)))) ;; => #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data ("foo" #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data ( ...)) ...)) ;; => #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8 data ("bar" nil ...))
ちゃんと nil なのか空ハッシュなのか判別できる!!
というわけで、今までの仕様はバグということにできて修正することができました。 @kiwanami さんありがとうございました!!
P.S.
Emacs 24.4 から標準実装されている M-x json-pretty-print
も似たような問題が起きていますが
M-x json-pretty-print
または M-x json-pretty-print-buffer
実行前に
(setq json-object-type 'hash-table)
とかしておくと、空ハッシュが壊れることはありません。