Mercurial > meta
comparison json.ur @ 22:8de201d70b91
Implement JSON typeclass for polymorphic variants.
author | Edward Z. Yang <ezyang@mit.edu> |
---|---|
date | Wed, 02 May 2012 11:47:37 -0400 |
parents | 6cd839818393 |
children | 9d6b931fbd13 |
comparison
equal
deleted
inserted
replaced
21:e7d64ea0f922 | 22:8de201d70b91 |
---|---|
220 (r, String.substring s {Start = 1, Len = String.length s - 1}) | 220 (r, String.substring s {Start = 1, Len = String.length s - 1}) |
221 else let | 221 else let |
222 val (name, s') = unescape s | 222 val (name, s') = unescape s |
223 val s' = skipSpaces s' | 223 val s' = skipSpaces s' |
224 val s' = if String.length s' = 0 || String.sub s' 0 <> #":" then | 224 val s' = if String.length s' = 0 || String.sub s' 0 <> #":" then |
225 error <xml>No colon after JSON object field naem</xml> | 225 error <xml>No colon after JSON object field name</xml> |
226 else | 226 else |
227 skipSpaces (String.substring s' {Start = 1, Len = String.length s' - 1}) | 227 skipSpaces (String.substring s' {Start = 1, Len = String.length s' - 1}) |
228 | 228 |
229 val (r, s') = @foldR2 [json] [fn _ => string] [fn ts => $(map option ts) -> $(map option ts) * string] | 229 val (r, s') = @foldR2 [json] [fn _ => string] [fn ts => $(map option ts) -> $(map option ts) * string] |
230 (fn [nm ::_] [t ::_] [r ::_] [[nm] ~ r] (j : json t) name' acc r => | 230 (fn [nm ::_] [t ::_] [r ::_] [[nm] ~ r] (j : json t) name' acc r => |
263 case v of | 263 case v of |
264 None => error <xml>Missing JSON object field {[name]}</xml> | 264 None => error <xml>Missing JSON object field {[name]}</xml> |
265 | Some v => v) fl r names, s') | 265 | Some v => v) fl r names, s') |
266 end | 266 end |
267 end} | 267 end} |
268 | |
269 fun json_variant [ts ::: {Type}] (fl : folder ts) (jss : $(map json ts)) (names : $(map (fn _ => string) ts)) : json (variant ts) = | |
270 {ToJson = fn r => let val jnames = @map2 [json] [fn _ => string] [fn x => json x * string] | |
271 (fn [t] (j : json t) (name : string) => (j, name)) fl jss names | |
272 in @Variant.destrR [ident] [fn x => json x * string] | |
273 (fn [p ::_] (v : p) (j : json p, name : string) => | |
274 "{" ^ escape name ^ ":" ^ j.ToJson v ^ "}") fl r jnames | |
275 end, | |
276 FromJson = fn s => | |
277 if String.length s = 0 || String.sub s 0 <> #"{" then | |
278 error <xml>JSON variant doesn't begin with brace</xml> | |
279 else | |
280 let | |
281 val (name, s') = unescape s | |
282 val s' = skipSpaces s' | |
283 val s' = if String.length s' = 0 || String.sub s' 0 <> #":" then | |
284 error <xml>No colon after JSON object field name</xml> | |
285 else | |
286 skipSpaces (String.substring s' {Start = 1, Len = String.length s' - 1}) | |
287 | |
288 val (r, s') = (@foldR2 [json] [fn _ => string] | |
289 [fn ts => ts' :: {Type} -> [ts ~ ts'] => variant (ts ++ ts') * string] | |
290 (fn [nm ::_] [t ::_] [rest ::_] [[nm] ~ rest] (j : json t) name' | |
291 (acc : ts' :: {Type} -> [rest ~ ts'] => variant (rest ++ ts') * string) [fwd ::_] [[nm = t] ++ rest ~ fwd] => | |
292 if name = name' | |
293 then | |
294 let val (v, s') = j.FromJson s' | |
295 in (make [nm] v, s') | |
296 end | |
297 else acc [fwd ++ [nm = t]] | |
298 ) | |
299 (fn [fwd ::_] [[] ~ fwd] => error <xml>Unknown JSON object variant name {[name]}</xml>) | |
300 fl jss names) [[]] ! | |
301 | |
302 val s' = skipSpaces s' | |
303 val s' = if String.length s' <> 0 && String.sub s' 0 = #"," then | |
304 skipSpaces (String.substring s' {Start = 1, Len = String.length s' - 1}) | |
305 else | |
306 s' | |
307 in | |
308 if String.length s' = 0 then | |
309 error <xml>JSON object doesn't end in brace</xml> | |
310 else if String.sub s' 0 = #"}" then | |
311 (r, String.substring s' {Start = 1, Len = String.length s' - 1}) | |
312 else error <xml>Junk after JSON value in object</xml> | |
313 end | |
314 } | |
315 | |
316 val json_unit : json unit = json_record {} {} |