Parsing JSON with Dart

dart, json

Solution

At the moment, JSON.parse only returns Lists (array), Maps, String, num, bool, and null (api ref).

I suspect that until reflection makes it way into the language, it won't be able to re-construct objects based upon the keys found in json.

You could, however, create a constructor in your MyJsonObject which took a string, called JSON.parse internally, and assigned the various values.

Something like this works in the dart editor:

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

}

A non trivial version would needs some loops and possible recursion if you had deeper nested levels.

Update: I've hacked together a non-trivial version (inspired by the post below), it's up on github (also taking Seth's comments re the constructor):

Problem

I want to be able to parse a string to an object that I can access using the dot notation e.g. myobject.property, instead of the array notation e.g. myobject['property']. The array notation works fine. Here's what I have so far. I have some XML: ``` <level1 name="level1name"> <level2 type="level2Type"> <entry>level2entry</entry> <entry>level2entry</entry> </level2> </level1> ``` Which converts to the JSON: ``` { "level1": { "name": "level1name", "level2": { "type": "level2Type", "entry": [ "level2entry", "level2entry" ] } } } ``` I have the following Dart code: ``` 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']}"); ``` which produce the (desired) output: ``` 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 ``` But when I try: ``` print("my test 1 == ${jsonObject.level1}"); ``` I get the following: ``` 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 ``` Ideally, I want an object that I can access using the dot notation and without the compiler giving warning about Object not having property. I tried the following: ``` 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}"); ``` but instead of giving me 'level1name' as hoped, I get: ``` Exception: type 'LinkedHashMapImplementation<String, Dynamic>' is not a subtype of type 'MyJSONObject' of 'jsonObject'. ``` What am I doing wrong here? Is there any way to do what I'm trying? Thanks.

Original source