Get Json Values for xValueMapper and yValueMapper

Hello, i have some hard time to implement the following Json in a Chart. Thanks in advance for some help.


```

{
  "measure": [
    {
      "count": 8,
      "range_array": [
        26.6, 27, 26.6, 2, 27.1, 26.8, 26.6, 26.8, 26.8, 27.2, 26.9, 0, 26.8,
        26.8, 26.9, 0, 27.1, 26.8, 27.2, 26.7
      ],
      "force_array": [
        26.6, 27, 26.6, 2, 27.1, 26.8, 26.6, 26.8, 26.8, 27.2, 26.9, 0, 26.8,
        26.8, 26.9, 0, 27.1, 26.8, 27.2, 26.7
      ]
    },
    {
      "count": 9,
      "range_array": [
        26.6, 27, 26.6, 2, 27.1, 26.8, 26.6, 26.8, 26.8, 27.2, 26.9, 0, 26.8,
        26.8, 26.9, 0, 27.1, 26.8, 27.2, 26.7
      ],
      "force_array": [
        26.6, 27, 26.6, 2, 27.1, 26.8, 26.6, 26.8, 26.8, 27.2, 26.9, 0, 26.8,
        26.8, 26.9, 0, 27.1, 26.8, 27.2, 26.7
      ]
    },
    {
      "count": 10,
      "range_array": [
        26.6, 27, 26.6, 2, 27.1, 26.8, 26.6, 26.8, 26.8, 27.2, 26.9, 0, 26.8,
        26.8, 26.9, 0, 27.1, 26.8, 27.2, 26.7
      ],
      "force_array": [
        26.6, 27, 26.6, 2, 27.1, 26.8, 26.6, 26.8, 26.8, 27.2, 26.9, 0, 26.8,
        26.8, 26.9, 0, 27.1, 26.8, 27.2, 26.7
      ]
    }
  ]
}



```


7 Replies

YG Yuvaraj Gajaraj Syncfusion Team July 4, 2022 04:34 PM UTC

Hi Carlos,


Greetings from Syncfusion. Here we have created the sample that will parse the JSON data from the locally stored JSON file, fetch the data from the decoded JSON string, and store it in the list. Then generate the list of line series based on the length of data and mapped the x and y values to the chart. We have attached the sample below for your requirement.


If you have any further queries, please get back to us.


Regards,

Yuvaraj.


Attachment: f175991_9b38ae7f.zip


CC Carlos Costa July 11, 2022 01:32 PM UTC

Hi Yuvaraj ,

thanks a lot for your help.

Today i tried out the sample code and it is nearly what i need.

I have two more questions. Unfortunately i am new to flutter.


In you example it draws all values inside the Json. I would need only to draw the last values from the Json.


Instead of all values 

```

{
    "measure": [
        {
            "count": 2,
            "range_array": [
                26.6,
                77,
                16.6,
                2,
                26.6,
                77
            ],
            "force_array": [
                6.6,
                57,
                66.6,
                12,
                7.6,
                57
            ]
        },
        {
            "count": 4,
            "range_array": [
                66.6,
                77,
                16.6,
                2,
                26.6,
                57
            ],
            "force_array": [
                9.6,
                47,
                96.6,
                32,
                17.6,
                67
            ]
        }
    ]
}

```


I need only the last values


```

        {
            "count": 4,
            "range_array": [
                66.6,
                77,
                16.6,
                2,
                26.6,
                57
            ],
            "force_array": [
                9.6,
                47,
                96.6,
                32,
                17.6,
                67
            ]
        }

```


 I tried to  create another sample that  parse the JSON data from the locally stored JSON file and prints it out on console with the last values inside the Json. Only i do not know how to implement this right now with the Chart


```

// ignore_for_file: avoid_print

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

import 'dart:convert';

import 'dart:async' show Future;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'JSON',
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  const Home({Key? key}) : super(key: key);

  @override
  HomeState createState() => HomeState();
}

class HomeState extends State<Home> {
  Future loadData() async {
    final jsonString = await rootBundle.loadString('assets/measurelist.json');
    final decodedJson = json.decode(jsonString);
    List<DataTitle> dataTileList = (decodedJson['measure'] as List)
        .map((jsonElement) => DataTitle.fromJson(jsonElement))
        .toList();
    print(dataTileList.last);
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('JSON Examples'),
      ),
      body: const Center(
        child: Text('JSON Examples'),
      ),
    );
  }
}

class DataModel {
  DataModel({this.measure});

  List<DataTitle>? measure;

  factory DataModel.fromJson(Map<String, dynamic> json) {
    return DataModel(
      measure: List<DataTitle>.from(
          json['title'].map((c) => DataTitle.fromJson(c)).toList()),
    );
  }
}

class DataTitle {
  DataTitle(
      {required this.number,
      required this.firstarray,
      required this.secondarray});

  int? number;
  List<double>? firstarray;
  List<double>? secondarray;

  DataTitle.fromJson(Map<String, dynamic> json) {
    number = json['count'];
    firstarray = json['range_array'] == null
        ? []
        : List<double>.from(json['range_array'].map((x) => x.toDouble()));
    secondarray = json['force_array'] == null
        ? []
        : List<double>.from(json['force_array'].map((x) => x.toDouble()));
  }
  @override
  String toString() {
    return 'DATA TITLE{Count: $number, RangeArray: $firstarray, ForceArray: $secondarray}';
  }
}

```

Follows also my actual code with the syncfusion_flutter_charts  packages using your example and also a print screen how the screen looks like.

```

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncfusion_flutter_charts/charts.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<List<ChartDataRange>> dataListRange = [];
  List<List<ChartDataForce>> dataListForce = [];

  Future<String> getJsonData() async {
    return await rootBundle.loadString('assets/measurelist.json');
  }

  Future loadStringRange() async {
    final String jsonString = await getJsonData();
    final dynamic jsonResponse = json.decode(jsonString);
    for (var i = 0; i < jsonResponse['measure'].length; i++) {
      List<dynamic> values = jsonResponse['measure'][i]['range_array'];
      List<ChartDataRange> chartDataR = [];
      for (var j = 0; j < values.length; j++) {
        chartDataR.add(ChartDataRange(j, values[j]));
      }
      dataListRange.add(chartDataR);
    }
  }

  Future loadStringForce() async {
    final String jsonString = await getJsonData();
    final dynamic jsonResponse = json.decode(jsonString);
    for (var i = 0; i < jsonResponse['measure'].length; i++) {
      List<dynamic> values = jsonResponse['measure'][i]['force_array'];
      List<ChartDataForce> chartDataF = [];
      for (var j = 0; j < values.length; j++) {
        chartDataF.add(ChartDataForce(j, values[j]));
      }
      dataListForce.add(chartDataF);
    }
  }

  @override
  void initState() {
    loadStringRange();
    loadStringForce();

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: FutureBuilder(
        future: getJsonData(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.hasData) {
            return Column(
              children: [
                SfCartesianChart(
                  series: getSeriesRange(),
                  //isTransposed: true,
                  legend: Legend(isVisible: true),
                  borderColor: Colors.red,
                  backgroundColor: Colors.green,
                ),
                SfCartesianChart(
                  series: getSeriesForce(),
                  //isTransposed: true,

                  legend: Legend(isVisible: true),
                  borderColor: Colors.black,
                  backgroundColor: Colors.yellow,
                ),
              ],
            );
          } else {
            return const CircularProgressIndicator();
          }
        },
      ),
    );
  }

  List<ChartSeries<ChartDataRange, num>> getSeriesRange() {
    List<ChartSeries<ChartDataRange, num>> seriesListRange = [];
    for (var index = 0; index < dataListRange.length; index++) {
      seriesListRange.add(
        //SplineAreaSeries<ChartDataRange, num>(
        SplineSeries<ChartDataRange, num>(
          dataSource: dataListRange[index],
          xValueMapper: (ChartDataRange data, _) => data.x,
          yValueMapper: (ChartDataRange data, _) => data.y,
          markerSettings: const MarkerSettings(isVisible: true),
          dataLabelSettings:
              const DataLabelSettings(isVisible: true, useSeriesColor: true),
          enableTooltip: false,
          animationDuration: 3000,
          animationDelay: 1000,
          name: 'Range',
          color: const Color.fromARGB(255, 157, 54, 124),
        ),
      );
    }
    return seriesListRange;
  }

  List<ChartSeries<ChartDataForce, num>> getSeriesForce() {
    List<ChartSeries<ChartDataForce, num>> seriesListForce = [];
    for (var index = 0; index < dataListForce.length; index++) {
      seriesListForce.add(
        //StackedLineSeries<ChartDataForce, num>(
        SplineSeries<ChartDataForce, num>(
          dataSource: dataListForce[index],
          xValueMapper: (ChartDataForce data, _) => data.x,
          yValueMapper: (ChartDataForce data, _) => data.y,
          markerSettings: const MarkerSettings(isVisible: true),
          dataLabelSettings:
              const DataLabelSettings(isVisible: true, useSeriesColor: true),
          animationDuration: 3000,
          animationDelay: 1000,
          name: 'Force',
          color: const Color.fromARGB(255, 26, 182, 104),
        ),
      );
    }
    return seriesListForce;
  }
}

class ChartDataRange {
  final num x;
  final num y;

  ChartDataRange(this.x, this.y);
}

class ChartDataForce {
  final num x;
  final num y;

  ChartDataForce(this.x, this.y);
}

```

Untitled.png


Like you see it show all values inside the Json. I would need only to display the last one and also to show the value somewhere of the "count" .

Something like the folowing picture.


Untitled2.png



YG Yuvaraj Gajaraj Syncfusion Team July 12, 2022 04:35 PM UTC

Hi Carlos,


We have analyzed your code snippet and found that you are add all the available data regarding force array and range array from the JSON response. For add only the last set of data in the JSON data from the response, you need to access the last value with the help of last function in the list. After get the JSON response here, `jsonResponse[‘measure’]` is the list of map data. So, you can access the last value like follows, `jsonResponse[‘measure’].last` then it gives last value from the list then you can store the respective value in the data list. We have attached the code snippet below to achieve your requirement.


Code snippet:

Future loadStringRange() async {

  final String jsonString = await getJsonData();

  final dynamic jsonResponse = json.decode(jsonString);

  // It will get the last value in the json

  List<dynamic> values = jsonResponse['measure'].last['range_array'];

  List<ChartDataRange> chartDataR = [];

  for (var j = 0; j < values.length; j++) {

    chartDataR.add(ChartDataRange(j, values[j]));

  }

  dataListRange.add(chartDataR);

}

 

Future loadStringForce() async {

  final String jsonString = await getJsonData();

  final dynamic jsonResponse = json.decode(jsonString);

  // It will get the last value in the json

  List<dynamic> values = jsonResponse['measure'].last['force_array'];

  List<ChartDataForce> chartDataF = [];

  for (var j = 0; j < values.length; j++) {

    chartDataF.add(ChartDataForce(j, values[j]));

  }

  dataListForce.add(chartDataF);

}



Regards,

Yuvaraj.



CC Carlos Costa July 13, 2022 07:36 PM UTC

Thanks a lot Yuvaraj for your help...)

It's exactly what I needed. 

Best regards and thanks again

Carlos



YG Yuvaraj Gajaraj Syncfusion Team July 14, 2022 01:27 PM UTC

Hi Carlos,


Thanks for the update. If you have any queries, please get back to us, we are always happy to assist you.


Regards,

Yuvaraj.



CC Carlos Costa July 21, 2022 12:52 PM UTC

Hi Yuvaraj ,

i come here again to ask for some help related to my previous question.

Thanks in advance for some help.

Meanwhile i changed my approach a little. Instead having the Json file in the assets folder, i change it to have it local storage under a folder.

The problem that i have now is that i get a error when i want to read from the file.


VAaEP.png


I think i get the above error because i am trying to read a write to the file at the same time. getJsonData() is called inside FutureBuilder in the Home Screen.


The idea is the following for a Desktop App

First i tried to fetch and save data locally in a Json file that i get over WebSocket. What is working.

Second i tried to display the data of the local Json file inside a Chart with your help. What is also working.

After i tried to combine the two above scenarios i one app and here i get the above error.


In my app i am using the following packages.

  1. Getx for the state manegment. https://pub.dev/packages/get
  2. Localstorage for the Json storage. https://pub.dev/packages/localstorage
  3. Syncfusion_flutter_charts for the Chart. https://pub.dev/packages/syncfusion_flutter_charts
  4. Path_provider to get access to file and folders. https://pub.dev/packages/path_provider

Follows the code that i have.
The code is divided in three separated files.
Main Function: ```
import 'package:flutter/material.dart';
import 'package:flutter_application_2/controller/diagram_controller.dart';
import 'package:flutter_application_2/home_screen.dart';
import 'package:get/get.dart';

void main() async {
  Get.put(DiagramController());
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const GetMaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomeScreen(),
    );
  }
}
```

HomeScreen:

```
import 'package:flutter_application_2/controller/diagram_controller.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GetBuilder(
        init: DiagramController(),
        initState: (_) {},
        builder: (gtxs1) {
          return FutureBuilder(
            future: gtxs1.getJsonData(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.hasData) {
                return Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Container(
                      //********Showing if Websocket is Connected or Disconnected*******
                      child: gtxs1.connectedS1Status
                          ? const Text(
                              "WEBSOCKET: CONNECTED",
                              style: TextStyle(
                                fontSize: 18,
                                color: Colors.green,
                              ),
                            )
                          : const Text(
                              "WEBSOCKET: DISCONNECTED",
                              style: TextStyle(
                                fontSize: 18,
                                color: Colors.red,
                              ),
                            ),
                    ),
                    //**********************Showing Range Diagram **********************
                    Column(
                      children: [
                        const Text(
                          'Range Diagram:',
                        ),
                        const SizedBox(
                          height: 5,
                        ),
                        SizedBox(
                          width: 800,
                          height: 280,
                          child: SfCartesianChart(
                            title: ChartTitle(
                              borderWidth: 2,
                              alignment: ChartAlignment.near,
                            ),
                            series: gtxs1.getSeriesRange(),
                            legend: Legend(isVisible: true),
                          ),
                        ),
                      ],
                    ),

                    const SizedBox(
                      height: 20,
                    ),
                    //**********************Showing Force Diagram **********************
                    Column(
                      children: [
                        const Text(
                          'Force Diagram:',
                        ),
                        const SizedBox(
                          height: 5,
                        ),
                        SizedBox(
                          width: 800,
                          height: 280,
                          child: SfCartesianChart(
                            title: ChartTitle(
                              borderWidth: 2,
                              alignment: ChartAlignment.near,
                            ),
                            series: gtxs1.getSeriesForce(),
                            legend: Legend(isVisible: true),
                          ),
                        ),
                      ],
                    ),
                  ],
                );
              } else {
                return const CircularProgressIndicator();
              }
            },
          );
        },
      ),
    );
  }
}
```


Controller:
```
// ignore_for_file: avoid_print

import 'package:get/get.dart';
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:path_provider/path_provider.dart';
import 'package:web_socket_channel/io.dart';
import 'package:localstorage/localstorage.dart';

final MeasureList list = MeasureList(); //List for LocalStorage

bool initialized = false; //for LocalStorage
int istcyclesJson = 0; //variable for istcycles
List<dynamic> istrangesensorJson = [0]; //variable for istrangesensor
List<dynamic> istforcesensorJson = [0]; //variable for istforcesensor

//***********************************************************************************************
//-----class MeasureItem for LocalStorage--------------------------------------------------------
//***********************************************************************************************
class MeasureItem {
  int titleCountJson;
  List<dynamic> titleRangeJson;
  List<dynamic> titleForceJson;
  MeasureItem({
    required this.titleCountJson,
    required this.titleRangeJson,
    required this.titleForceJson,
  });
  toJSONEncodable() {
    Map<String, dynamic> m = {};
    m['count_array'] = titleCountJson;
    m['range_array'] = titleRangeJson;
    m['force_array'] = titleForceJson;
    return m;
  }
}

//***********************************************************************************************
//-----class MeasureList for LocalStorage--------------------------------------------------------
//***********************************************************************************************
class MeasureList {
  List items = [];

  toJSONEncodable() {
    return items.map((item) {
      return item.toJSONEncodable();
    }).toList();
  }
}

class DiagramController extends GetxController {
  static DiagramController get to => Get.find();

  List<List> dataListRange = [];
  List<List> dataListForce = [];

  LocalStorage storage = LocalStorage('/Measure/measure.json');

  final MeasureList list = MeasureList();

  late IOWebSocketChannel channel;
  late bool connectedS1Status;

  Directory? rootPath;

  //**********************************************************************
  @override
  void onInit() {
    connectedS1Status = false;

    createFileFolder();

    Future.delayed(
      Duration.zero,
      () async {
        channelconnect();
      },
    );

    Future.delayed(
      const Duration(milliseconds: 1000),
      () async {
        loadStringRange();
        loadStringForce();
      },
    );

    super.onInit();
  }

//***********************************************************************************************
//-----Channelconnect----------------------------------------------------------------------------
//***********************************************************************************************
  channelconnect() {
    try {
      channel = IOWebSocketChannel.connect("ws://192.168.1.100:80");

      channel.stream.listen(
        (message) {
          print(message);
          Map<String, dynamic> jsondat = json.decode(message);
          String data = json.encode(jsondat);
          if (data.contains("cycle")) {
            connectedS1Status = true;
            update();
          }
          if (data.contains("count_array")) {
            istcyclesJson = jsondat['count_array'];
            istrangesensorJson = jsondat['range_array'];
            istforcesensorJson = jsondat['force_array'];
            _save();
            //update();
          }
        },
        onDone: () {
          print("Web socket is closed");

          connectedS1Status = false;
        },
        onError: (error) {
          print(error.toString());
        },
      );
    } catch (_) {
      print("error on connecting to websocket.");
    }
    //update();
  }

//***********************************************************************************************
//-----Functions to create and generate Json List using LocalStorage-----------------------------
//***********************************************************************************************

  //...................................................
  void _save() {
    _addItem(istcyclesJson, istrangesensorJson, istforcesensorJson);
    print("SAVE");
    // update();
  }

  //...................................................
  _addItem(int titlecount, List<dynamic> titlerange, List<dynamic> titleforce) {
    final item = MeasureItem(
        titleCountJson: titlecount,
        titleRangeJson: titlerange,
        titleForceJson: titleforce);
    list.items.add(item);
    _saveToStorage();
    //update();
  }

  //...................................................
  _saveToStorage() {
    storage.setItem('measure', list.toJSONEncodable());
    //update();
  }

//***********************************************************************************************
//-----Functions to create Folder and File if not exist and write to the file some zero values
//-----not to get error when display the chart and the file is empty
//***********************************************************************************************
  Future createFileFolder() async {
    rootPath = await getApplicationDocumentsDirectory();

    Directory sampleFolder = Directory('${rootPath!.path}/Measure');
    if (!sampleFolder.existsSync()) {
      sampleFolder.createSync();
    }
    File sampleFile =
        await File('${sampleFolder.path}/measure.json').create(recursive: true);
    if (!sampleFile.existsSync()) {
      sampleFolder.createSync();
    }
    final file = sampleFile;
    return file.writeAsString(
        '{"measure": [{"count": 0,"range_array": [0,0,0],"force_array": [0,0,0]}]}');
  }

//**********************************************************************
  Future<String> getJsonData() async {
    rootPath = await getApplicationDocumentsDirectory();
    Directory sampleFolder = Directory('${rootPath!.path}/Measure');
    await File('${sampleFolder.path}/measure.json').create(recursive: true);
    return await File('${sampleFolder.path}/measure.json').readAsString();
  }




//**********************************************************************

  Future loadStringRange() async {
    final String jsonString = await getJsonData();
    final dynamic jsonResponse = json.decode(jsonString);
    List<dynamic> values = jsonResponse['measure'].last['range_array'];
    List chartDataR = [];
    for (var j = 0; j < values.length; j++) {
      chartDataR.add(ChartDataRange(j, values[j]));
    }

    dataListRange.add(chartDataR);
    update();
  }

//**********************************************************************

  Future loadStringForce() async {
    final String jsonString = await getJsonData();
    final dynamic jsonResponse = json.decode(jsonString);
    List<dynamic> values = jsonResponse['measure'].last['force_array'];
    List chartDataF = [];
    for (var j = 0; j < values.length; j++) {
      chartDataF.add(ChartDataForce(j, values[j]));
    }

    dataListForce.add(chartDataF);
    update();
  }

//**********************************************************************

  Listnum>> getSeriesRange() {
    Listnum>> seriesListRange = [];
    for (var index = 0; index < dataListRange.length; index++) {
      seriesListRange.add(
        SplineSeriesnum>(
          dataSource: dataListRange[index],
          xValueMapper: (ChartDataRange data, _) => data.x,
          yValueMapper: (ChartDataRange data, _) => data.y,
        ),
      );
    }
    return seriesListRange;
  }

//**********************************************************************

  Listnum>> getSeriesForce() {
    Listnum>> seriesListForce = [];
    for (var index = 0; index < dataListForce.length; index++) {
      seriesListForce.add(
        SplineSeriesnum>(
          dataSource: dataListForce[index],
          xValueMapper: (ChartDataForce data, _) => data.x,
          yValueMapper: (ChartDataForce data, _) => data.y,
        ),
      );
    }
    return seriesListForce;
  }
}

//**********************************************************************
class ChartDataRange {
  final num x;
  final num y;

  ChartDataRange(this.x, this.y);
}

//**********************************************************************
class ChartDataForce {
  final num x;
  final num y;

  ChartDataForce(this.x, this.y);
}
```






YG Yuvaraj Gajaraj Syncfusion Team July 22, 2022 01:32 PM UTC

Hi Carlos,


The reported issue is not related to our chart widget. If so, please provide some more details to replicate the issue on our end.


Regards,

Yuvaraj.



Loader.
Up arrow icon