Haskell の JSON パーサ

This entry was posted by on Thursday, 27 April, 2006
> >http://www.tom.sfc.keio.ac.jp/~sakai/d/?date=20060427#p02 > おお。 JSON パーサは楽そうなわりにあると便利そうだと思いつつ作業したことはなかった。 > >HughesPJ を使った stringify はこんなところでしょうか。 > >import Text.PrettyPrint.HughesPJ

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 > >ちょっと試してみる。 > >Prelude> :l JSON
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"
}
}
> >ふむ、まぁこんなところかなあ。ブレースの閉じがつねに改行されてしまうのが気になりますが、短いときには改行しない処理ってできないかな。 >

Comments are closed.