Flutter: complex json serialization. Parsing json string to provide into UI

292

So Far from the json you provided I have created and example for you in the listview format just check it out.

following is the json you provided:

{
    "first_name": "First Name",
    "batch_name": "Batch 1",
    "enrolled_subjects": [
        "Subject 4",
        "Subject 5"
    ],
    "batch_timetable": {
        "Mon": {
            "Subject 4": [
                "6:00 PM - 7:00 PM"
            ],
            "Subject 5": [
                "5:00 PM - 6:00 PM",
                "7:00 PM - 8:00 PM"
            ],
            "Subject 6": [
                "8:00 PM - 9:00 PM"
            ]
        },
        "Tue": {
            "Subject 4": [
                "6:00 PM - 7:00 PM"
            ],
            "Subject 5": [
                "7:00 PM - 8:00 PM"
            ],
            "Subject 6": [
                "8:00 PM - 9:00 PM"
            ]
        }
    }
}

Based on the json I have created a ui

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _isLoading = false;
  List<Timings> timingsList = List();

  Future<String> loadFromAssets() async {
    return await rootBundle.loadString('json/parse.json');
  }

  @override
  void initState() {
    super.initState();
    dataLoadFunction();
  }

  dataLoadFunction() async {
    setState(() {
      _isLoading = true;
    });
    String jsonString = await loadFromAssets();
    Map newStringMap = json.decode(jsonString);
    //print(newStringMap['batch_timetable']);

    newStringMap['batch_timetable'].forEach((key, value) {
      List<Subjects> subjectsList = List();

      print(key);

      // print(value);
      value.forEach((key, value) {
        print(key);
        print(value);
        List<dynamic> timingValue = List();
        timingValue.add(value);
        Subjects subjects = Subjects(subjectName: key, timings: timingValue);
        subjectsList.add(subjects);
      });

      Timings sampleObject = Timings(
        day: key,
        subjectList: subjectsList,
      );
      timingsList.add(sampleObject);
    });
    print(timingsList.length);


    setState(() {
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: _isLoading
            ? CircularProgressIndicator()
            : ListView.builder(
                itemCount: timingsList.length,
                shrinkWrap: true,
                itemBuilder: (BuildContext context, int index) {
                  return Card(
                    child: Column(
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.only(top:10,left:15),
                          child: Row(
                            children: <Widget>[
                              Text('Day :'),
                              Text(timingsList[index].day),
                            ],
                          ),
                        ),
                        Divider(color: Colors.grey,),
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            Text(' Day wise Subjects are :'),
                            ListView.builder(
                              itemCount: timingsList[index].subjectList.length,
                              shrinkWrap: true,
                              itemBuilder: (BuildContext context, int i) {
                                return Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: <Widget>[
                                    Text(timingsList[index]
                                        .subjectList[i]
                                        .subjectName),
                                    for (int j = 0;
                                        j <
                                            timingsList[index]
                                                .subjectList[i]
                                                .timings
                                                .length;
                                        j++)
                                      Text(timingsList[index]
                                          .subjectList[i]
                                          .timings[j]
                                          .toString()),
                                  ],
                                );
                              },
                            )
                          ],
                        )
                      ],
                    ),
                  );
                },
              ),
      ),
    );
  }
}

class Timings {
  final String day;
  final List<Subjects> subjectList;

  Timings({
    this.day,
    this.subjectList,
  });
}

class Subjects {
  final String subjectName;
  final List<dynamic> timings;

  Subjects({this.subjectName, this.timings});
}

I have just added the data, you can decorate it based on your desired ui:

What have I achieved in this code

1) Data will be fetched dynamically so that even if the json changes it will adapt accordingly.

2) Added it in the list view format ,you can do as you want.

Provided the sample ui that I have made enter image description here

Let Me know if it works.

Share:
292
JC18
Author by

JC18

Updated on December 21, 2022

Comments

  • JC18
    JC18 over 1 year

    Here is the json string that I get by http request. The aim is to display subjects according to the current weekday.

    {
        "first_name": "First Name",
        "batch_name": "Batch 1",
        "enrolled_subjects": [
            "Subject 4",
            "Subject 5"
        ],
        "batch_timetable": {
            "Mon": {
                "Subject 4": [
                    "6:00 PM - 7:00 PM"
                ],
                "Subject 5": [
                    "5:00 PM - 6:00 PM",
                    "7:00 PM - 8:00 PM"
                ],
                "Subject 6": [
                    "8:00 PM - 9:00 PM"
                ]
            },
            "Tue": {
                "Subject 4": [
                    "6:00 PM - 7:00 PM"
                ],
                "Subject 5": [
                    "7:00 PM - 8:00 PM"
                ],
                "Subject 6": [
                    "8:00 PM - 9:00 PM"
                ]
            }, ...so on upto "Sun"
        }
    }
    

    How to set Model Class for this json string?

    I tried this Model Class but it gives this error : type '_InternalLinkedHashMap<dynamic, dynamic>' is not a subtype of type 'Map<String, List<dynamic>>'

    I also tried Model Class by quicktype, but I think that won't work in this case.

    class HomePageModel {
      HomePageModel({
        this.firstName,
        this.batchName,
        this.subjects,
        this.timetable,
      });
    
      String firstName;
      String batchName;
      List<String> subjects;
      Map timetable;
    
      factory HomePageModel.fromJson(Map<String, dynamic> json) => HomePageModel(
            firstName: json["first_name"],
            batchName: json["batch_name"],
            subjects: List<String>.from(json["subjects"].map((x) => x)),
            timetable: Map.from(json["timetable"])
                .map((key, value) => MapEntry(key, value)),
          );
    
      Map<String, dynamic> toJson() => {
            "first_name": firstName,
            "batch_name": batchName,
            "subjects": List<dynamic>.from(subjects.map((x) => x)),
            "timetable":
                Map.from(timetable.map((key, value) => MapEntry(key, value))),
          };
    }
    

    I am using FutureBuilder to display this data into UI. Any help would be appreciated.