0

Can anyone tell me how to parse arrays of arrays of object in flutter. When I am parsing the json I am getting error as List<dynamic> is not a subtype of type Map<String, dynamic>.

I have used quicktype to write the model class and I am trying to print the worksheetData in the Future but I am getting error. Below is my json file which needs to be parsed. Please help me to fix this issue. Stuck since two days.

[
    {
        "_id": "5ebae61440315c41995eccc7",
        "projectName": "NSM",
        "sheetName": "Priliminaries - A1",
        "worksheetData": [
            [
                {
                    "serial": "Sl.No",
                    "description": "ITEM DESCRIPTION",
                    "quantity": "QTY.",
                    "unit": "UNIT",
                    "unitrate": "UNIT PRICE",
                }
            ],
            null,
            [
                {
                    "serial": "1.1",
                    "description": "Allowance for CAR policy, Mobilization, demobilization after works, Firstaid boxes, Fire extinguishers etc.",
                    "quantity": 1,
                    "unit": "Lot",
                    "unitrate": 12500,
                }
            ],
            [
                {
                    "serial": "1.2",
                    "description": "Demolition of existing gypsum partitions, ceilings, necessary floor tiles etc and cart away debris if any",
                    "quantity": 0,
                    "unit": "Lot",
                    "unitrate": 5000,
                }
            ]
        ],
        "__v": "0"
    },
    {
        "_id": "5ebae61440315c41995eccc8",
        "projectName": "NSM",
        "sheetName": "General works -A2",
        "worksheetData": [
            [
                {
                    "serial": "Sl.No",
                    "description": "ITEM DESCRIPTION",
                    "quantity": "QTY.",
                    "unit": "UNIT",
                    "unitrate": "UNIT PRICE",
                }
            ],
            null,
            [
                {
                    "serial": "1.1",
                    "description": "Allowance for CAR policy, Mobilization, demobilization after works, Firstaid boxes, Fire extinguishers etc.",
                    "quantity": 1,
                    "unit": "Lot",
                    "unitrate": 12500,
                }
            ],
            [
                {
                    "serial": "1.2",
                    "description": "Demolition of existing gypsum partitions, ceilings, necessary floor tiles etc and cart away debris if any",
                    "quantity": 0,
                    "unit": "Lot",
                    "unitrate": 5000,
                }
            ]
        ],
        "__v": "0"
    }
]

Main.dart

class WorkSheet extends StatefulWidget {
  const WorkSheet({Key key}) : super(key: key);
  @override
  _WorkSheetState createState() => new _WorkSheetState();
}

class _WorkSheetState extends State<WorkSheet> {
  // List<ArticleslistData> articleslist = [];
  // List<ArticleslistData> list;

  @override
  void initState() {
    setState(() {
      loadSheetDataFromAssets();
    });
    super.initState();
  }

  Future loadSheetDataFromAssets() async {
    var jsonData = await rootBundle.loadString('assets/Vibyor.json');
    var data = json.decode(jsonData);
    ArticleslistData articleslistData = new ArticleslistData.fromJson(data);
     print('data : ${articleslistData.worksheetData[0]}');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Work sheet data'),
      ),
      body: FutureBuilder(
          future: loadSheetDataFromAssets(),
          builder: (context, snapshot) {
            return snapshot.data != null
                ? Text(snapshot.data)
                : Center(child: CircularProgressIndicator());
          }),
    );
  }
}

enter image description here

3
  • 1
    add Your code to question Commented Jun 5, 2020 at 12:09
  • please add class ArticlesListData to Your question, since I don't know what fields it has. Commented Jun 5, 2020 at 16:54
  • Here is the model class pastebin.com/SAMfg6gr Commented Jun 5, 2020 at 17:11

1 Answer 1

1

I've refactored Your classes:

class ArticleslistData {
  String sId;
  String projectName;
  String sheetName;
  List<WorksheetData> worksheetData = [];
  String sV;

  ArticleslistData(this.sId, this.projectName, this.sheetName, this.worksheetData, this.sV);

  static ArticleslistData fromMap(Map<String, dynamic> map) {
    List<WorksheetData> worksheetData = [];
    if (map['worksheetData'] != null) {
      for (Iterable row in map['worksheetData']) {
        if (row == null) continue;
        for (Map map in row) {
          worksheetData.add(WorksheetData.fromMap(map));
        }
      }
    }

    return ArticleslistData(
      map['_id'],
      map['projectName'],
      map['sheetName'],
      worksheetData,
      map['__v']
    );
  }

  Map<String, dynamic> toMap() {
    return {
      "_id":            this.sId,
      "projectName":    this.projectName,
      "sheetName":      this.sheetName,
      "worksheetData":  this.worksheetData,
      "__v":            this.sV
    };
  }
}

class WorksheetData {
  String serial;
  String description;
  String quantity;
  String unit;
  String unitrate;

  WorksheetData(this.serial, this.description, this.quantity, this.unit, this.unitrate);

  static WorksheetData fromMap(Map map) {
    return WorksheetData(
        map['serial'].toString(),
        map['description'].toString(),
        map['quantity'].toString(),
        map['unit'].toString(),
        map['unitrate'].toString()
    );
  }

  Map<String, dynamic> toMap() {
    return {
      "serial":       this.serial,
      "description":  this.description,
      "quantity":     this.quantity,
      "unit":         this.unit,
      "unitrate":     this.unitrate
    };
  }
}

Usage:

Future loadSheetDataFromAssets() async {
  var jsonData = await rootBundle.loadString('assets/Vibyor.json');
  var data = json.decode(jsonData);

  this.articleslist = [];
  List<ArticleslistData> items = [];
  data.forEach((item) {
    items.add(ArticleslistData.fromMap(element));
  });
  this.articleslist = items;

  print('data : ${this.articleslist[0].worksheetData[0]}');
  return this.articleslist;
}

Don't forget to uncomment following from Your _WorkSheetState widget:

List<ArticleslistData> articleslist = [];

P.S. fromJson and toJson method names are not valid, so I renamed them to fromMap, toMap since You were working maps. JSON is string that You decoded, after decode it becomes Iterable and Map.

Small hint: if You want to easily solve Your issues - use IntelliJ Idea Community Edition and do debug by setting breakpoints.

idea community edition

Sign up to request clarification or add additional context in comments.

4 Comments

this throws me an error _TypeError (type 'String' is not a subtype of type 'Iterable<dynamic>') in model class
print(data); what You see?
import 'dart:convert'; at top of file and use: jsonDecode(jsonData) instead of json.decode
still the same issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.