Mathematica's list of built-in formats is pretty extensive; however, JSON is not on that list. Is there an existing solution for generating and parsing JSON in Mathematica, or are we going to have to roll our own solution?
Great question! A really quick-and-dirty partial solution to JSON parsing would be this:
ToExpression[StringReplace[json, {"["->"{", "]"->"}", ":"->"->"}]]
Ie, just replace square brackets with curly braces and colons with arrows and then eval it. All that remains is to not do those substitutions inside of strings.
There's probably a more elegant solution to the not-within-strings problem, but the first thing to come to mind is to do substitutions like "{"->"(*MAGICSTRING*){"
and then, after the eval (when comments outside of strings will have disappeared), reverse those substitutions.
That's slightly easier said than done but the following JSON parser seems to work:
cat = StringJoin@@(ToString/@{##})&; (* Like sprintf/strout in C/C++. *)
eval = ToExpression; (* Mathematica function names are too verbose! *)
parseJSON[json_] := eval@StringReplace[cat@FullForm@eval[StringReplace[json,
{"[" -> "(*MAGIC[*){",
"]" -> "(*MAGIC]*)}",
":" -> "(*MAGIC:*)->"}]],
{"(*MAGIC[*){" -> "[",
"(*MAGIC]*)}" -> "]",
"(*MAGIC:*)->" -> ":"}]
(cat
and eval
are convenience functions. Simply cat = ToString
would work in this case but I like this more general version that concatenates all its arguments into a string.).
Finally, here's a function to generate JSON (which does need the more general cat
):
genJSON[x_String] := "\"" <> cat[x] <> "\""
genJSON[x_] := cat[x] /; NumberQ[x]
genJSON[a_ -> b_] := genJSON[a] <> ":" <> genJSON[b]
genJSON[{x__Rule}] := "{" <> cat @@ Riffle[genJSON /@ {x}, ", "] <> "}"
genJSON[{x___}] := "[" <> cat @@ Riffle[genJSON /@ {x}, ", "] <> "]"
genJSON[x_] := cat[x]