2012-04-05 15 views
8

Desidero essere in grado di analizzare una stringa su un oggetto a cui è possibile accedere utilizzando la notazione punto ad es. myobject.property, anziché la notazione di matrice ad es. MyObject [ 'proprietà']. La notazione array funziona correttamente. Ecco cosa ho finora.Parsing JSON con Dart

ho qualche XML:

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

che converte il JSON:

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

ho il seguente codice 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']}"); 

che producono l'uscita (desiderato) :

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 

Ma quando provo:

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

ottengo il seguente:

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 

Idealmente, vorrei un oggetto che io possa accedere utilizzando la notazione punto e senza il compilatore dà avvertimento su Object non avere proprietà. Ho provato quanto segue:

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}"); 

ma invece di dare 'level1name' come sperato, ottengo:

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

che cosa sto facendo male qui? C'è un modo per fare ciò che sto provando? Grazie.

+0

Questo è un po 'una parte; dovresti essere in grado di convertire da un oggetto in javascript e da javascript in JSON. – will

risposta

12

Al momento, JSON.parse restituisce solo elenchi (array), Maps, String, num, bool e null (api ref).

Sospetto che fino a quando la riflessione non si farà strada nel linguaggio, non sarà in grado di ricostruire gli oggetti in base alle chiavi trovate in json.

Si potrebbe tuttavia creare un costruttore nel MyJsonObject che ha preso una stringa, chiamata internamente JSON.parse e assegnato i vari valori.

Qualcosa di simile a questo funziona nell'editor dardo:

#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); 

} 

Una versione non banale avrebbe bisogno di qualche loop e possibile ricorsione se si ha livelli più profondi nidificati.

Update: Ho messo insieme una versione non banale (ispirata al post qui sotto), è up on github (prendendo anche i commenti di Seth re il costruttore):

+0

È un peccato per quel limite di linguaggio.Tuttavia, questa è stata una risposta eccezionale. Esattamente quello che stavo cercando. Grazie Chris :) –

+0

Potrei suggerire di utilizzare un costruttore chiamato, qualcosa come MyJSONObject.fromJson (jsonString) o simile. Ciò crea un intento più ovvio per il costruttore. –

4

Chris è completamente a destra. Aggiungerò solo che il parser JSON può essere modificato per restituire un oggetto un po 'più ricco (qualcosa come JsonMap invece di puro Map) che potrebbe consentire jsonObj.property implementando noSuchMethod. Ciò ovviamente andrebbe peggio di jsonObj['property'].

+1

Ispirato da questo commento, ho avuto un trucco e ora è su github: http://github.com/chrisbu/dartwatch-JsonObject –