Haskell の JSON パーサ
stringify :: Value -> String
stringify = show . stringifyDoc
stringifyDoc :: Value -> Doc
stringifyDoc (String s) = stringifyString s
stringifyDoc (Number x)
| isInfinite x = error "can't stringify infinity"
| isNaN x = error "can't stringify NaN"
| otherwise = double x
stringifyDoc (Object m) = lbrace <+> join comma [fsep [stringifyString k <> colon, nest 2 (stringifyDoc v)] | (k,v) <- M.toList m] $+$ rbrace
stringifyDoc (Array xs) = lbrack <+> join comma (map stringifyDoc xs) <+> rbrack
stringifyDoc (Bool b) = if b then text "true" else text "false"
stringifyDoc Null = text "null"
stringifyString :: String -> Doc
stringifyString s = doubleQuotes $ text $ concatMap f s
where f '"' = "\\\""
f '\\' = "\\\\"
f '\b' = "\\b"
f '\f' = "\\f"
f '\n' = "\\n"
f '\r' = "\\r"
f '\t' = "\\t"
f c | isControl c = printf "\\u%04x" c
| otherwise = [c]
join :: Doc -> [Doc] -> Doc
join s = fcat . punctuate s
>
Compiling JSON ( JSON.hs, interpreted )
Ok, modules loaded: JSON.
*JSON> s <- readFile "test.json"
*JSON> case parse s of Just x -> stringifyDoc x
Loading package parsec-1.0 ... linking ... done.
{ "has_error": false,
"user":
{ "image_url":
"http://www.hatena.ne.jp/users/ha/hatena/profile.gif",
"name": "hatena",
"thumbnail_url":
"http://www.hatena.ne.jp/users/ha/hatena/profile_s.gif"
}
} > >ふむ、まぁこんなところかなあ。ブレースの閉じがつねに改行されてしまうのが気になりますが、短いときには改行しない処理ってできないかな。 >