1

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

Ravindra S. Patil
  • 11,757
  • 3
  • 13
  • 40

1 Answers1

1

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,
  };
}
Dev
  • 6,628
  • 2
  • 25
  • 34
  • Thank you so much, I appreciate your answer. can you share your LinkedIn profile? – Ravindra S. Patil Apr 21 '22 at 11:28
  • 1
    Sure bro, updated my profile get it from there. – Dev Apr 21 '22 at 11:33
  • @Dev-Can you tell me, as you have named the subjects and you have colored them according to them, I mean you can color whatever data comes from API, that is without naming the subjects and Without color, for example you can refer my answers [here](https://stackoverflow.com/a/71231241/13997210),and [here](https://stackoverflow.com/a/71320740/13997210), – Ravindra S. Patil Apr 22 '22 at 17:34
  • yes you can do that also. As the json had no color info and the default colors in flutter chart is shades of blue that is sometimes confusiong. i just used the map to show coloring feature of the chart. if you have colors in json input you can use that also. Itts jus a demo. – Dev Apr 23 '22 at 10:49
  • Yes I know about shades of blue but I think their is confusing if you are free so try to solve my issue what I say. Thanks in advance – Ravindra S. Patil Apr 23 '22 at 11:30
  • Do you have a json with all subjects and colors of it? Or do you want to use random colors without naming the subjects and Without color. – Dev Apr 25 '22 at 04:21
  • No I dont have json with colors of subjects, I want random colors without naming the subject. – Ravindra S. Patil Apr 25 '22 at 04:47
  • 1
    Now check is it ok? – Dev Apr 25 '22 at 04:50
  • I have done this example using API but one thing I cant understood when screen is open it gives the **The getter 'length' was called on null** error, why it gives the error, then open my graph working correct and also labels not display as well as tooltip also when I click on that chart can you check once again I was stuck in this problem some days but not found correct solution – Ravindra S. Patil Jun 01 '22 at 09:00
  • one thing the tooltip not display when I click on graph I have shows in above image `65 ABC` can you help me in that – Ravindra S. Patil Jun 01 '22 at 09:04
  • may be you are missing async nature of API Call. Can you update the example with how you are binding the values of graphs using the API Call – Dev Jun 09 '22 at 07:03
  • _The getter 'length' was called on null_ is resolved I have message you on linkedIn – Ravindra S. Patil Jun 09 '22 at 07:33