2012-04-05 9 views
8

Chcę móc analizować ciąg znaków do obiektu, do którego można uzyskać dostęp za pomocą notacji kropkowej, np. myobject.property, zamiast notacji tablicowej, np. myobject ['property']. Zapis tablicowy działa dobrze. Oto, co mam do tej pory.Parsowanie JSON z Dart

Mam XML:

<level1 name="level1name"> 
    <level2 type="level2Type"> 
    <entry>level2entry</entry> 
    <entry>level2entry</entry> 
    </level2> 
</level1> 

które konwertuje do formatu JSON:

{ 
    "level1": { 
    "name": "level1name", 
    "level2": { 
     "type": "level2Type", 
     "entry": [ 
     "level2entry", 
     "level2entry" 
     ] 
    } 
    } 
} 

Mam następujący kod Dart:

Object jsonObject = JSON.parse("""{ 
     "level1": { 
     "name": "level1name", 
     "level2": { 
      "type": "level2Type", 
      "entry": [ 
      "level2entry", 
      "level2entry" 
      ] 
     } 
     } 
    } 
"""); 

    print("my test 1 == ${jsonObject}"); 
    print("my test 2 == ${jsonObject['level1']}"); 
    print("my test 3 == ${jsonObject['level1']['name']}"); 

które produkują (pożądany) wyjście :

my test 1 == {level1: {name: level1name, level2: {type: level2Type, entry: [level2entry, level2entry]}}} 
my test 2 == {name: level1name, level2: {type: level2Type, entry: [level2entry, level2entry]}} 
my test 3 == level1name 

Ale gdy próbuję:

print("my test 1 == ${jsonObject.level1}"); 

uzyskać następujące:

Exception: NoSuchMethodException : method not found: 'get:level1' 
Receiver: {level1: {name: level1name, level2: {type: level2Type, entry: [level2entry, level2entry]}}} 
Arguments: [] 
Stack Trace: 0. Function: 'Object.noSuchMethod' url: 'bootstrap' line:717 col:3 

Idealnie chcę obiekt, który można uzyskać dostęp za pomocą notacji kropki i bez kompilator daje ostrzeżenie o obiekcie nie ma własności. Próbowałem następujące:

class MyJSONObject extends Object{ 
    Level1 _level1; 
    Level1 get level1() => _level1; 
    set level1(Level1 s) => _level1 = s; 
} 

class Level1 { 
    String _name; 
    String get name() => _name; 
    set name(String s) => _name = s; 
} 
... 
MyJSONObject jsonObject = JSON.parse("""{ 
     "level1": { 
     "name": "level1name", 
     "level2": { 
      "type": "level2Type", 
      "entry": [ 
      "level2entry", 
      "level2entry" 
      ] 
     } 
     } 
    } 
"""); 
... 
print("my test 1 == ${jsonObject.level1.name}"); 

ale zamiast dać mi „level1name”, jak się spodziewano, otrzymuję:

Exception: type 'LinkedHashMapImplementation<String, Dynamic>' is not a subtype of type 'MyJSONObject' of 'jsonObject'. 

Co robię źle tutaj? Czy jest jakiś sposób, aby zrobić to, co próbuję? Dzięki.

+0

To jest na bok; powinieneś być w stanie przekonwertować obiekt z javascript iz javascript na JSON. – will

Odpowiedz

12

W tej chwili JSON.parse zwraca tylko listy (tablica), mapy, łańcuch, liczbę, bool i wartość null (api ref).

Podejrzewam, że dopóki refleksja nie rozwinie się w języku, nie będzie w stanie ponownie skonstruować obiektów w oparciu o klucze znalezione w jsonie.

Można jednak utworzyć konstruktor w swoim obiekcie MyJsonObject, który pobierał ciąg znaków, zwany wewnętrznie JSON.parse i przypisywał różne wartości.

Coś jak to działa w edytorze dart:

#import("dart:json"); 
class Level2 { 
    var type; 
    var entry; 
} 

class Level1 { 
    var name; 
    var level2;   
} 

class MyJSONObject { 
    Level1 level1; 


    MyJSONObject(jsonString) { 
    Map map = JSON.parse(jsonString); 

    this.level1 = new Level1(); 
    level1.name = map['level1']['name']; 
    level1.level2 = new Level2(); 
    level1.level2.type = map['level1']['level2']['type']; 
    //etc... 

    } 
} 

main() { 
    var obj = new MyJSONObject(json); 
    print(obj.level1.level2.type); 

} 

Non wersja trywialne by potrzebuje pętle i ewentualne rekursji jeśli miał głębsze poziomy zagnieżdżonych.

Aktualizacja: Mam hacked razem wersję nietrywialne (zainspirowaną poniżej post), to up on github (biorąc również komentarze Setha ponownie konstruktora):

+0

Szkoda w tym ograniczeniu języka.Jednak była to znakomita odpowiedź. Dokładnie to, czego szukałem. Dzięki Chris :) –

+0

Mogę zaproponować użycie nazwanego konstruktora, coś jak MyJSONObject.fromJson (jsonString) lub podobne. Stwarza to bardziej oczywiste zamiary konstruktora. –

4

Chris jest całkowicie w porządku. Dodam tylko, że parser JSON mógłby zostać zmodyfikowany, aby zwrócić nieco bogatszy obiekt (coś w rodzaju JsonMap zamiast czystego Map), który może pozwolić na jsonObj.property przez implementację noSuchMethod. To oczywiście byłoby gorsze niż jsonObj['property'].

+1

Zainspirowany tym komentarzem, mam na tym hack, i jest teraz na github: http://github.com/chrisbu/dartwatch-JsonObject –