Ответ 1
ОБНОВЛЕНИЕ: Как отмечено в ответе Пиллси, JSON является встроенным форматом для импорта и экспорта по математике 8: http://reference.wolfram.com/mathematica/ref/format/JSON.html, Но, как обсуждалось в комментариях, следующее представляется более надежным решением по Mathematica 10.4.1:
ПРЕДУПРЕЖДЕНИЕ. Это включает в себя выполнение eval (ToExpression), поэтому не используйте это для анализа строк из ненадежных источников.
Во-первых, очень быстрое и грязное частичное решение для разбора JSON будет следующим:
ToExpression[StringReplace[json, {"["->"{", "]"->"}", ":"->"->"}]]
Т.е. просто замените квадратные скобки фигурными скобками и двоеточиями со стрелками, а затем сравните их. Остается только не делать этих подстановок внутри строк. (Также нужны еще несколько подстановок для нулевой, истинной, ложной и научной нотации.)
Вероятно, более элегантное решение проблемы не внутри строк, но первое, что приходит на ум, - это делать подстановки, такие как "{"->"(*MAGICSTRING*){"
, а затем после eval (когда комментарии за пределами строк исчезнут), отмените эти замены.
(PS: Возвращаясь к этому позже, я действительно доволен умностью этого, и он кажется совершенно надежным. Волшебные строки FTW!)
Это немного легче сказать, чем сделать, но, похоже, работает следующий парсер JSON:
cat = [email protected]@(ToString/@{##})&; (* Like sprintf/strout in C/C++. *)
eval = ToExpression; (* Mathematica function names are too verbose! *)
parseJSON[json_String] := With[{tr = {"[" -> "(*_MAGIC__[__*){",
"]" -> "(*_MAGIC__]__*)}",
":" -> "(*_MAGIC__:__*)->",
"true" -> "(*_MAGIC__t__*)True",
"false" -> "(*_MAGIC__f__*)False",
"null" -> "(*_MAGIC__n__*)Null",
"e" -> "(*_MAGIC__e__*)*10^",
"E" -> "(*_MAGIC__E__*)*10^"}},
[email protected][[email protected]@eval[StringReplace[json, tr]], Reverse/@tr]]
(cat
и eval
являются удобными функциями. Просто cat = ToString
будет работать в этом случае, но мне нравится эта более общая версия, которая объединяет все его аргументы в строку.).
Наконец, здесь функция для генерации JSON (для которой требуется более общий cat
, а также другая функция утилиты для отображения чисел в подходящем для JSON образом):
re = RegularExpression;
jnum[x_] := StringReplace[
[email protected][[email protected], ExponentFunction->(Null&)], [email protected]"\\.$"->""]
genJSON[a_ -> b_] := genJSON[a] <> ":" <> genJSON[b]
genJSON[{x__Rule}] := "{" <> cat @@ Riffle[genJSON /@ {x}, ", "] <> "}"
genJSON[{x___}] := "[" <> cat @@ Riffle[genJSON /@ {x}, ", "] <> "]"
genJSON[Null] := "null"
genJSON[True] := "true"
genJSON[False] := "false"
genJSON[x_] := jnum[x] /; NumberQ[x]
genJSON[x_] := "\"" <> StringReplace[cat[x], "\""->"\\\""] <> "\""