Mercurial > meta
changeset 2:478524b9d23a
Parsed a JSON record
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Thu, 02 Dec 2010 11:59:55 -0500 |
parents | 4d103b4450ee |
children | 189245a3c075 |
files | json.ur tests/testJson.ur |
diffstat | 2 files changed, 72 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/json.ur Thu Dec 02 11:35:01 2010 -0500 +++ b/json.ur Thu Dec 02 11:59:55 2010 -0500 @@ -198,4 +198,57 @@ "" => "" | _ => "," ^ acc)) "" fl jss names r ^ "}", - FromJson = fn _ => error <xml>Uhoh!</xml>} + FromJson = fn s => + let + fun fromJ s (r : $(map option ts)) : $(map option ts) * string = + if String.length s = 0 then + error <xml>JSON object doesn't end in brace</xml> + else if String.sub s 0 = #"}" then + (r, String.substring s {Start = 1, Len = String.length s - 1}) + else let + val (name, s') = unescape s + val s' = skipSpaces s' + val s' = if String.length s' = 0 || String.sub s' 0 <> #":" then + error <xml>No colon after JSON object field naem</xml> + else + skipSpaces (String.substring s' {Start = 1, Len = String.length s' - 1}) + + val (r, s') = @foldR2 [json] [fn _ => string] [fn ts => $(map option ts) -> $(map option ts) * string] + (fn [nm ::_] [t ::_] [r ::_] [[nm] ~ r] (j : json t) name' acc r => + if name = name' then + let + val (v, s') = j.FromJson s' + in + (r -- nm ++ {nm = Some v}, s') + end + else + let + val (r', s') = acc (r -- nm) + in + (r' ++ {nm = r.nm}, s') + end) + (fn _ => error <xml>Unknown JSON object field name {[name]}</xml>) + fl jss names r + + val s' = skipSpaces s' + val s' = if String.length s' <> 0 && String.sub s' 0 = #"," then + skipSpaces (String.substring s' {Start = 1, Len = String.length s' - 1}) + else + s' + in + fromJ s' r + end + in + if String.length s = 0 || String.sub s 0 <> #"{" then + error <xml>JSON record doesn't begin with brace</xml> + else + let + val (r, s') = fromJ (String.substring s {Start = 1, Len = String.length s - 1}) + (@map0 [option] (fn [t ::_] => None) fl) + in + (@map2 [option] [fn _ => string] [id] (fn [t] (v : option t) name => + case v of + None => error <xml>Missing JSON object field {[name]}</xml> + | Some v => v) fl r names, s') + end + end}
--- a/tests/testJson.ur Thu Dec 02 11:35:01 2010 -0500 +++ b/tests/testJson.ur Thu Dec 02 11:59:55 2010 -0500 @@ -3,18 +3,21 @@ val json_abcd : json {A : int, B : float, C : string, D : bool} = json_record {A = "a", B = "b", C = "c", D = "d"} -fun main () : transaction page = return <xml><body> - {[toJson (1 :: 2 :: 8 :: [])]}<br/> - {[fromJson "[1,2, 8]" : list int]} - <hr/> - {[toJson (1.2 :: 2.4 :: (-8.8) :: [])]}<br/> - {[fromJson "[1.4,-2.7, 8.215506]" : list float]} - <hr/> - {[toJson ("hi" :: "bye" :: "tricky\\\" one!" :: [])]}<br/> - {[fromJson "[\"abc\", \"\\\\whoa\"]" : list string]} - <hr/> - {[toJson (True :: False :: True :: [])]}<br/> - {[fromJson "[true,false, true]" : list bool]} - <hr/> - {[toJson {A = 1, B = 2.3, C = "Hi", D = True}]} -</body></xml> +fun main () : transaction page = + d <- return (fromJson "{\"a\": 1, \"b\": 2.3, \"c\": \"Hi\", \"d\": true}" : {A : int, B : float, C : string, D : bool}); + return <xml><body> + {[toJson (1 :: 2 :: 8 :: [])]}<br/> + {[fromJson "[1,2, 8]" : list int]} + <hr/> + {[toJson (1.2 :: 2.4 :: (-8.8) :: [])]}<br/> + {[fromJson "[1.4,-2.7, 8.215506]" : list float]} + <hr/> + {[toJson ("hi" :: "bye" :: "tricky\\\" one!" :: [])]}<br/> + {[fromJson "[\"abc\", \"\\\\whoa\"]" : list string]} + <hr/> + {[toJson (True :: False :: True :: [])]}<br/> + {[fromJson "[true,false, true]" : list bool]} + <hr/> + {[toJson {A = 1, B = 2.3, C = "Hi", D = True}]}<br/> + A: {[d.A]}, B: {[d.B]}, C: {[d.C]}, D: {[d.D]} + </body></xml>