JSON: Difference between revisions

1,793 bytes added ,  4 years ago
(→‎{{header|Standard ML}}: + generic loop)
Line 3,548:
</pre>
=={{header|Standard ML}}==
Works on Unix/Linux/BSD with jq (github.com/stedolan/jq/ ) installed. Data storage in strings, to be sure thatso floating point numbers arecan be written back as received, in a recursive polymorphic structure, which can also be used to store the data as SML-types.
<lang Standard ML>
val Validate = fn jsonstring =>
Line 3,580:
end;
 
local
 
 
datatype 'a element = elem of string * 'a | markerb of int ;
datatype content('a,'b) element = elem of 'a * ='b | textmarkerb of stringint ; | block of content element list | arr of content list |marker of int ; (* < internal structure v *)
datatype 'a content = value of 'a | block of ('a,'a content) element list | arr of 'a content list |marker of int ;
 
exception Dtype of string ;
val unarr = fn arr lst => lst | _ => (raise Dtype "unarr" ; []) ;
val unblock = fn block lst => lst | _ => (raise Dtype "unblock" ; []) ;
 
 
(* --- example loop to apply a function 'dothis', which returns type jvals, to the structure ---- *)
 
datatype jvals = St of string | It of IntInf.int | Rl of real | Bl of bool ; (* returned type by 'dothis' *)
 
val rec gothruAndDo = fn dothis => fn storedObject =>
let
val walk = fn elem ( n, value v) => elem (dothis n , value (dothis v) )
| elem ( n, block v) => elem (dothis n , block ( (gothruAndDo dothis) (rev (tl (rev v)))) )
| elem ( n, arr v) => elem (dothis n , arr ( List.map (block o (gothruAndDo dothis) o unblock) (rev (tl (rev v))) ) )
| _ => elem (St "", value (It (IntInf.fromInt ~1)))
in
List.map walk storedObject
end;
 
(* ------------------------------------ end of loop example ------------------------------------ *)
 
 
local
 
exception Dtype of string ;
val markbToInt = fn markerb NrChars => NrChars | _ => (raise Dtype "markerb!" ; ~1) ;
val markToInt = fn marker NrChars => NrChars | _ => (raise Dtype "marker!" ; ~1) ;
 
val untext = fn text lst => lst | _ => (raise Dtype "untxt" ; "") ;
val unarr = fn arr lst => lst | _ => (raise Dtype "unarr" ; []) ;
val unblock = fn block lst => lst | _ => (raise Dtype "unblock" ; []) ;
 
 
fun readarr rtag rc = fn #"]"::S => [ marker (List.length S) ] (* process array *)
| S => let val tmp = (rtag rc ("",S)) in (block tmp) ::
( readarr rtag rc ( List.drop (S,(List.length S) - markbToInt ( hd (rev tmp))) )) end ;
Line 3,600 ⟶ 3,620:
 
 
val rec readNaVa = fn rc : string * char list -> string content * char list => fn
("",[]) => []
| (sr,[]) => [ elem (sr, textvalue "") ]
| (sr,#":":: #"["::S) =>
let val tmp = arr (readarr readNaVa rc S) in (* valuefield is array *)
( elem (sr, tmp )) :: (readNaVa rc ("" , List.drop (S,(List.length S) - (markToInt (hd (rev(unarr tmp)))) ) ))
end
| (sr, #":":: #"{"::S) =>
let val tmp = readNaVa rc ("",S ) in (* valuefield is object *)
( elem (sr, block tmp)) :: (readNaVa rc ("" , List.drop (S,(List.length S) -(markbToInt ( hd (rev tmp)))) ))
end
Line 3,614 ⟶ 3,634:
| (sr,#"}"::S) => [ markerb (List.length S) ]
| (sr,#":"::S) =>
let val tmp = rc ("",S) in (* valuefield is basic *)
elem ( sr, #1 tmp) :: (readNaVa rc ("", #2 tmp ) )
end
| (sr,#","::S) => readNaVa rc (sr , S)
| (sr,#"{"::a::S) => readNaVa rc (sr^(str a) , S)
| (sr,a::S) => readNaVa rc (sr^(str a) , S) ; (* name field *)
 
val rec readcontent = fn
(sc,a::[]) => (textvalue ( sc^(str a) ),[])
| (sc,#","::t) => (textvalue sc , t)
| (sc, #"}"::t) => (textvalue sc , #"}"::t)
| (sc, #"]"::t) => (textvalue sc , #"]"::t)
| (sc, a::t) => readcontent( ( sc^(str a) ),t) ;
 
Line 3,633 ⟶ 3,653:
val rec put = fn
[] => ""
| (elem h)::t => (#1 h) ^ ":" ^ ( ( fn textvalue x=> x
| block x => "{" ^ (put x )
| arr x => "[" ^ String.concat (( List.map (fn x=> "{"^( (put o unblock) x)^"," ) (rev (tl (rev x))))) ^ "]" ) (#2 h))
^ ","
^ (put t)
Line 3,648 ⟶ 3,668:
(Substring.tokens (fn x=> x= tok ) (Substring.full S) )) ) ^ (if tok = #"}" then str tok else "" )
 
in
 
in
 
val storeJsString = fn input =>
Line 3,658 ⟶ 3,678:
 
end ;
</lang>Example
example
<lang Standard ML>
val testString="{\"firstName\":\"John\",\"lastName\":\"Smith\",\"age\":25,\"address\":{\"streetAddress\":\"21 2nd Street\",\"city\":\"New York\",\"state\":\"NY\",\"postalCode\":\"10021\"},\"phoneNumber\":[{\"type\":\"home\",\"numbers\":[{\"o\":\"212 555-1234\",\"h\":\"119 323-1234\"}]},{\"type\":\"fax\",\"number\":\"646 555-4567\"}]}" ;
 
testString = (writeJS o storeJsString) testString ;
val it = true : bool (* because the test string was unformatted *)
 
val toMlVal = fn input =>
case String.isPrefix "\"" input
of true => St (String.substring (input,1,(String.size input)-2) )
| _ => case IntInf.fromString input of
SOME n => It n
| NONE => case Real.fromString input of
SOME x => Rl x
| NONE => case Bool.fromString input of
SOME b => Bl b
| NONE => St "" ;
 
val toMlVal = fn: string -> jvals
 
List.nth (gothruAndDo toMlVal (storeJsString testString ) ,3);
 
val it =
elem
(St "address",
block
[elem (St "streetAddress", value (St "21 2nd Street")),
elem (St "city", value (St "New York")),
elem (St "state", value (St "NY")),
elem (St "postalCode", value (St "10021"))]):
(jvals, jvals content) element
</lang>
 
Anonymous user