Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have a Dart class that I am using as a node class for a tree data structure.

My goal here is to encode objects of this class and its child nodes recursively.

I have a toJson() method that takes the child Nodes List and calls jsonencode on them.

class Node{
  String name;
  Map<String, String> attributes;
  List<Node> children = List<Node>();

 Node(this.name, attributes) {
    this.attributes = attributes;
    this.children = List<Node>();
  }

  Node.fromJson(Map<dynamic,dynamic> _map) {    
    this.name = _map['name'];    
    this.children = new List<Node>();
    this.attributes = _map['attributes'][0]; 

    for(var i = 0; i < _map['children'].length;i++){
      Node temp = new Node.fromJson(_map['children'][i]);
      this.addChild(temp);
    }
  }

  Map<String, dynamic> toJson() => {
        'name': name,
        'attributes': [attributes],
        'children': [
          ...this.children.map(jsonEncode)        
        ]
      };
}

I have a unit test i created to test this functionality:

        Node nodeMap = {
          "name": "Name",
          "attributes": [
            {"#htag1": "tagval1"}
          ],
          "children": [
            {
              "name": "NameChild1",
              "attributes": [
                {"#htag2": "tagval2"}
              ],
              "children": []
            },
            {
              "name": "NameChild2",
              "attributes": [
                {"#htag3": "tagval3"}
              ],
              "children": []
            }
          ] 
        };

        UNode unodeInst = new UNode.fromJson(nodeMap);

        // Act
        var nodeCreate = nodeInst.toJson();
        // Assert
        expect(nodeCreate, equals(nodeMap));

Here is the output of my unit test

  Expected: {
              'name': 'Name',
              'attributes': [{'#htag1': 'tagval1'}],
              'children': [
                {
                  'name': 'NameChild1',
                  'attributes': [{'#htag2': 'tagval2'}],
                  'children': []
                },
                {
                  'name': 'NameChild2',
                  'attributes': [{'#htag3': 'tagval3'}],
                  'children': []
                }
              ]
            }
    Actual: {
              'name': 'Name',
              'attributes': [{'#htag1': 'tagval1'}],
              'children': [
                '{"name":"NameChild1","attributes":[{"#htag2":"tagval2"}],"children":[]}',
                '{"name":"NameChild2","attributes":[{"#htag3":"tagval3"}],"children":[]}'
              ]
            }
     Which: at location ['children'][0] is '{"name":"NameChild1","attributes":[{"#htag2":"tagval2"}],"children":[]}' which expected a map

As you see its not encoding my object correctly.

I believe this is happening because when i reclusively call jsonencode this method returns a string that is placed into the children array.

I believe part of my problem is that i dont fully understand the d diffrence between jsonencode() and toJson().

It is my understanding that jsonencode() calls toJson().. but jsonencode() returns a string and toJson() returns a Map<String, dynamic>.. so i think what i want here is to call toJson() recursively and not jsonencode.

Does this sound correct?

But i cannot figure out how to do this on a list in this situation.

I have tried the following

...this.children.map(this.toJson()) 

but i get "The argument type 'Map<String, dynamic>' can't be assigned to the parameter type 'dynamic Function(Node)'"

...this.children.forEach((element) {element.toJson()})

but i get "Spread elements in list or set literals must implement 'Iterable'"

Does this mean i have to implement the Iterable interface in my class?

question from:https://stackoverflow.com/questions/65541164/tojson-invalid-when-recursively-encode-tree-data-structure

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
267 views
Welcome To Ask or Share your Answers For Others

1 Answer

You're just using the map method incorrectly. Use the following instead.

[
  ...this.children.map((e) => e.toJson())
]

It's also unnecessary to use spread with a literal list or use this. You can simplify the code to just

children.map((e) => e.toJson()).toList()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...