'Flutter JSON to DataTable

Would you be able to help me a bit as I am struggling with a conversion of API response into JSON/Object and then into DataTable.

I have a Stateful widget where I am getting data during Init:

class _AlertState extends State<Alert> {

  final Api _api_service = Api();
  late Future<List<Data>> _watchdog;

  @override
  void initState() {
    _watchdog = _api_service.get_watchdog();
    super.initState();
  }

get_watchdog()

    Future<List<Data>> get_watchdog() async {

    var data = utf8.encode('{xxx}');

    Response raw_response = await post(url, headers: headers, body: data);

    if (raw_response.statusCode == 200) {

      var res_json = jsonDecode(raw_response.body);
      Watchdog watchdog = Watchdog.fromJson(res_json);

      return watchdog.result!.data!;
    } else{
      Api.error_message = raw_response.statusCode as String;
              throw Exception('xxx');
    }
  }

Watchdog object

class Watchdog {
  String? version;
  Error? error;
  Result? result;


  Watchdog({this.version, this.error, this.result});

  Watchdog.fromJson(Map<String, dynamic> json) {
    version = json['version'];
    result = json['error'] != null ? new Result.fromJson(json['error']) : null;
    result = json['result'] != null ? new Result.fromJson(json['result']) : null;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['version'] = this.version;
    if (this.result != null) {
      data['result'] = this.result!.toJson();
    }
    if (this.error != null) {
      data['error'] = this.result!.toJson();
    }
    return data;
  }
}

class Result {
  String? now;
  List<Data>? data;

  Result({this.now, this.data});

  Result.fromJson(Map<String, dynamic> json) {
    now = json['now'];
    if (json['data'] != null) {
      data = <Data>[];
      json['data'].forEach((v) {
        data!.add(new Data.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['now'] = this.now;
    if (this.data != null) {
      data['data'] = this.data!.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class Data {
  String? status;
  String? problemtype;
  String? message;

  Data({this.status, this.problemtype, this.message});

  Data.fromJson(Map<String, dynamic> json) {
    status = json['status'];
    problemtype = json['problemtype'];
    message = json['message'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['status'] = this.status;
    data['problemtype'] = this.problemtype;
    data['message'] = this.message;
    return data;
  }

  @override
  String toString() {
    return "Data(status: $status, problemtype: $problemtype, message: $message)";
  }
}

class Error {
  int? code;
  String? message;
  String? name;

  Error({this.code, this.message, this.name});

  Error.fromJson(Map<String, dynamic> json) {
    code = json['code'];
    message = json['message'];
    name = json['name'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['code'] = this.code;
    data['message'] = this.message;
    data['name'] = this.name;
    return data;
  }
}

Can you please point me how to convert now the returned Future into Datatable when I press the button?

Widget build(BuildContext context) {
    return Column(
      children: [
        SingleChildScrollView(
          scrollDirection: Axis.horizontal,
          child: DataTable(
            columns: <DataColumn>[
              DataColumn(
                label: Text('Status'),
              ),
              DataColumn(
                label: Text('Description'),
              ),
            ],
            // rows: ???
          ),
        ),
        TextButton(
          onPressed: () {
            if (_watchdog != null){
              _watchdog.
            } else{
              print('empty');
            }
          },
          child: Text('print'),
        )
      ],
    );
  }

Thanks.



Solution 1:[1]

Can you please point me how to convert now the returned Future into Datatable when I press the button

=>you want to get data from API after clicking on the button, right ?

Solution ^^

In this case , you can't use a FutureBuilder Widget. Therefore ,include the last code in the stateful widget then you may simply use setState

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

   @override
    State<HomePage> createState() => _HomePageState();
   }

  class _HomePageState extends State<HomePage> {

  List<Data>? _watchdogs;   // ---> remove Future

  @override
  Widget build(BuildContext context) {
     return SafeArea(
       child: Scaffold(
       body: Center(
          child: Column(
            children: [
            SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Visibility(
              visible: _watchdogs!=null,
              child: DataTable(
                columns: <DataColumn>[
                  DataColumn(
                    label: Text('Status'),
                  ),
                  DataColumn(
                    label: Text('Description'),
                  ),
                ], rows: _watchdogs!.map((_watchdog) =>
                  DataRow(cells: [
                    //example
                    DataCell(Text(${_watchdog.name})),
                    DataCell(Text(${_watchdog.type})),
                  ])
              ).toList(),
              ),
            )
          ),
          ElevatedButton(
            onPressed: () async{
              if (_watchdogs != null){
                //get data from API, not forget to add async and await here
                List<Data> data =await   _api_service.get_watchdog();
                setState(() {
                  _watchdogs=data;
                });
            } else{
              print('empty');
              }
            },
            child: Text('print'),
          )

        ],
      ),
    ),
  ),
);
}



}


  

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1