Search code examples
jsonflutterdartchartssyncfusion-chart

Put JSON Data in Flutter Stacked Chart


I have try to put my JSON data in flutter Stacked Chart.

I already work on simple charts using JSON Data like bar, column, pie, Doughnut charts etc.

I have refer

  1. stacked-column-chart(syncfusion_flutter_charts),
  2. Grouped Bar Chart(charts_flutter)
  3. Stack Overflow Que-Ans

below like my API response/JSON String

 [{
        "name": "ABC",
        "subject": [{
                "name": "Math",
                "marks": "54"
            },
            {
                "name": "Physics",
                "marks": "65"
            }
        ]
    },
    {
        "name": "PQR",
        "subject": [{
                "name": "Chemistry",
                "marks": "53"
            },
            {
                "name": "Biology",
                "marks": "22"
            },
            {
                "name": "English",
                "marks": "7 "
            },
            {
                "name": "Math",
                "marks": "12"
            }
        ]
    }, {
        "name": "JKL",
        "subject": [{
                "name": "Chemistry",
                "marks": "53"
            },
            {
                "name": "Biology",
                "marks": "22"
            },
            {
                "name": "English",
                "marks": "79 "
            },
            {
                "name": "Math",
                "marks": "12"
            },
            {
                "name": "Physics",
                "marks": "72"
            }
        ]
    }
]

Or I want below type of graph using JSON Data

Wanted Stacked Graph

Note: Suggest me my JSON string is wrong, you can create your own JSON data and display the output


Solution

  • Using charts_flutter. Please customize it for your usecase its a bare minimum implementation to validate that its working for your json.

       import 'package:flutter/material.dart';
    import 'dart:math';
    import 'package:flutter/material.dart';
    import 'package:charts_flutter/flutter.dart' as charts;
    
    import 'dart:convert';
    
    
    class StackedBarChart extends StatelessWidget {
    
      final bool animate;
    
      StackedBarChart({this.animate = false});
    
    
    
    
      // EXCLUDE_FROM_GALLERY_DOCS_END
    
      @override
      Widget build(BuildContext context) {
        String jsonString = '[{"name":"ABC","subject":[{"name":"Math","marks":"54"},{"name":"Physics","marks":"65"}]},{"name":"PQR","subject":[{"name":"Chemistry","marks":"53"},{"name":"Biology","marks":"22"},{"name":"English","marks":"7 "},{"name":"Math","marks":"12"}]},{"name":"JKL","subject":[{"name":"Chemistry","marks":"53"},{"name":"Biology","marks":"22"},{"name":"English","marks":"79 "},{"name":"Math","marks":"12"},{"name":"Physics","marks":"72"}]}]';
        final studentMarks = studentMarksFromJson(jsonString);
    
        var subjects = <Subject?>{};
        var subjectsDist = <Subject?>{};
        int c=0;
        for (var stdnt in studentMarks) {
          for (var subjs in stdnt.subject) {
            if (!subjectsDist.where((element) => element?.name==subjs.name).isNotEmpty) {
              subjs.sno=c++;
              subjectsDist.add(subjs);
            }
          }
        }
    
        print(subjectsDist.length);
    
        List<List<OrdinalMarks>> SubjectData = [];
        for (var subjs in subjectsDist) {
          List<OrdinalMarks> marksData = [];
          for (var stdnt in studentMarks) {
            if (stdnt.subject
                .where((element) => element.name == subjs?.name).isNotEmpty) {
              var temp = stdnt.subject
                  .where((element) => element.name == subjs?.name)
                  .first;
              marksData.add(OrdinalMarks(temp.name, int.parse(temp.marks),stdnt.name));
            } else {
              marksData.add(OrdinalMarks(subjs!.name, 0,stdnt.name));
            }
          }
          SubjectData.add(marksData);
        }
    
    
    
        var palettes = charts.MaterialPalette.getOrderedPalettes(subjectsDist.length+2);
    
    
    
        int cnt=0;
        List<charts.Series<OrdinalMarks, String>> chartData = [
        ];
    
        for(var d in SubjectData)
          {
            chartData.add(new charts.Series<OrdinalMarks, String>(
              id: d.first.subjectName,
              domainFn: (OrdinalMarks m, _) => m.studentName,
              measureFn: (OrdinalMarks m, _) => m.marks,
              data: d,
              fillColorFn: ( subj, _) {
               // print(subj.subjectName+": subj.subjectName :" + pallets[subj.subjectName].toString()??charts.MaterialPalette.blue.shadeDefault.toString());
               return  palettes.elementAt( subjectsDist.where((element) => element?.name==subj.subjectName).first?.sno??0 ).shadeDefault; //pallets[subj.subjectName]??charts.MaterialPalette.blue.shadeDefault;
              },
              colorFn: ( subj, _) {
              //  print(subj.subjectName+": subj.subjectName :" + pallets[subj.subjectName].toString()??charts.MaterialPalette.blue.shadeDefault.toString());
                return palettes.elementAt(subjectsDist.where((element) => element?.name==subj.subjectName).first?.sno??0).shadeDefault;
              },
            ));
    
          }
    
        return Scaffold(
          // Use Obx(()=> to update Text() whenever count is changed.
            appBar: AppBar(title: Text("Chart")),
    
            // Replace the 8 lines Navigator.push by a simple Get.to(). You don't need context
    
    
            body:new charts.BarChart(
              chartData,
              animate: animate,
              behaviors: [new charts.SeriesLegend(showMeasures: true)],
              animationDuration: Duration(seconds: 3),
    
    
    
            ));
      }
    
    
    }
    
    /// Sample ordinal data type.
    class OrdinalMarks {
      final String subjectName;
      final int marks;
      final String studentName;
    
    
      OrdinalMarks(this.subjectName, this.marks,this.studentName);
    }
    
    
    List<StudentMarks> studentMarksFromJson(String str) => List<StudentMarks>.from(json.decode(str).map((x) => StudentMarks.fromJson(x)));
    
    String studentMarksToJson(List<StudentMarks> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
    
    class StudentMarks {
      StudentMarks({
        required this.name,
        required this.subject,
      });
    
      String name;
      List<Subject> subject;
    
      factory StudentMarks.fromJson(Map<String, dynamic> json) => StudentMarks(
        name: json["name"],
        subject: List<Subject>.from(json["subject"].map((x) => Subject.fromJson(x))),
      );
    
      Map<String, dynamic> toJson() => {
        "name": name,
        "subject":  List<dynamic>.from(subject.map((x) => x.toJson())),
      };
    }
    
    class Subject {
      Subject({
        required this.name,
        required this.marks,
      });
    
      String name;
      String marks;
      int? sno;
    
      factory Subject.fromJson(Map<String, dynamic> json) => Subject(
        name: json["name"],
        marks: json["marks"],
      );
    
      Map<String, dynamic> toJson() => {
        "name": name,
        "marks": marks,
      };
    }