2010-04-13 17 views

Odpowiedz

18

UPDATE: Jak wspomniano w odpowiedzi Pillsy, w JSON jest wbudowany w formacie Importerów i Eksporterów jak z Mathematica 8: http://reference.wolfram.com/mathematica/ref/format/JSON.html. Ale, jak zostało to omówione w komentarzach, wydaje się, że poniższe rozwiązanie jest bardziej niezawodne niż w Mathematica 10.4.1:

OSTRZEŻENIE: To wymaga wykonania eval (ToExpression), więc nie używaj tego do analizowania ciągów od niezaufanych źródła.

pierwsze, bardzo szybkiego i brzydka częściowe rozwiązanie JSON parsowania byłoby to:

ToExpression[StringReplace[json, {"["->"{", "]"->"}", ":"->"->"}]] 

Czyli po prostu zastąpić nawiasy kwadratowe z klamrami i dwukropkami ze strzałkami, a następnie eval go. Pozostaje tylko , a nie dokonanie tych zmian w łańcuchach. (Potrzebne są jeszcze kilka zastępstw dla zapisu zerowego, prawdziwego, fałszywego i naukowego).

Prawdopodobnie istnieje bardziej eleganckie rozwiązanie problemu niewiążącego się z łańcuchami, ale pierwszą rzeczą, o której należy pamiętać, jest zrobienie podstawienia takie jak "{"->"(*MAGICSTRING*){", a następnie po eval (gdy znikną komentarze poza ciągami), odwróć te podstawienia. (PS: Wracając do tego później, jestem całkiem zadowolony z tego sprytu i wygląda na to, że jest całkowicie niezawodny Magiczne łańcuchy FTW!)

To trochę łatwiej powiedzieć niż zrobić, ale następujący parser JSON wydaje się działać:

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 i eval są funkcjami wygoda Wystarczy cat = ToString będzie działać w tym przypadku, ale mi się podoba bardziej ogólną wersję, która skleja wszystkie swoje argumenty do łańcucha.).

Wreszcie tutaj funkcją wygenerować JSON (który ma potrzeby bardziej ogólne cat, jak również inną funkcję użytkową do wyświetlania liczb w taki sposób, JSON odpowiednio)

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], "\""->"\\\""] <> "\"" 
+0

@Pillsy, daj nam znać, jeśli to działa dla Ciebie lub jeśli znajdziesz jakieś błędy lub ulepszenia. Twoje odpowiedzi były dla mnie niesamowicie pomocne, więc chciałem odpłacić za przysługę! – dreeves

+0

Używam tego teraz na prawdę, więc jest to właściwie dobrze przetestowane w tym momencie. Zwróć uwagę na poprawki błędów właśnie teraz! – dreeves

+3

Mathematica 8 może w zasadzie mieć możliwości importowania JSON-a, ale odmawia załadowania prostego pliku o wielkości 18 mb .json (działa na zawsze). Twoja funkcja działa jak urok. Dziękuję Ci. – phantomas1234

2

This guy ma sprytnego przykład parsowania kodu JSON w Mathematica

+0

Myślę, że to tylko wyciągnięcie liczb z wyrażenia JSON, prawda? – dreeves

+0

tak. To wspaniała rzecz w JSON, tak łatwa do przeanalizowania. –

+0

Tak, kocham JSON. Przez "wyciągnięcie liczb z wyrażeń JSON" miałem na myśli, w przeciwieństwie do pełnego analizowania, do izomorficznego zagnieżdżonego wyrazu Mathematica. Moja odpowiedź próbuje to zrobić. – dreeves