how to show data on listview builder from http POST request Result Flutter

3.3k views Asked by At

I want to parsing nested json with flutter http POST. I write my code, and no show data in my ListView.builder

This Request Json:

{
 "nomorAccount": "1234567890"
}

This Json Nested Response

{
  "responseCode": "0000",
  "responseMessage": "Success",
  "tanggal": "20200131",
  "jam": "112301",
  "content": [
    {
      "nomorAccount": "1234567890",
      "namaPegawai": "DEVELOPMENT",
      "statusAccount": "AKTIF",
      "jenisAccount": "TABUNGAN",
      "produkAccount": "GOLD",
      "mataUang": "IDR",
      "saldoEfektif": "+100055033221,84",
      "saldoBuku": "+100055058221,84"
    }
  ]
}

Model

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;


class PostResult {
    String responseCode;
    String responseMessage;
    String tanggal;
    String jam;
    String nomorAccount;
    String namaPegawai;
    String statusAccount;
    String jenisAccount;
    String produkAccount;
    String mataUang;
    String saldoEfektif;
    String saldoBuku;

    PostResult({this.responseCode,this.responseMessage,this.tanggal,this.jam,this.nomorAccount,this.namaPegawai,this.statusAccount,this.jenisAccount,this.produkAccount,this.mataUang,this.saldoEfektif,this.saldoBuku});

    factory PostResult.createPostResult(Map<String, dynamic> object)
    {
      return PostResult(
        responseCode: object['responseCode'],
        responseMessage: object['responseMessage'],
        tanggal: object['tanggal'],
        jam: object['jam'],
        nomorAccount: object['nomorAccount'],
        namaPegawai: object['namaPegawai'],
        statusAccount: object['statusAccount'],
        jenisAccount: object['jenisAccount'],
        produkAccount: object['produkAccount'],
        mataUang: object['mataUang'],
        saldoEfektif:object['saldoEfektif'],
        saldoBuku:object['saldoBuku']
      );
    }

    static Future<PostResult> connectToAPI(String nomorAccount) async {
      String apiURL = "http://contoh.com/api";
      String username = "username";
      String password = "12345678";
      var bytes = utf8.encode("$username:$password");

      var credentials = base64.encode(bytes);
      var headers = {
        "Content-Type": "application/json",
        "Authorization": "Basic $credentials"
      };

      var requestBody = jsonEncode({ 'nomorAccount': nomorAccount});
      http.Response apiResult = await http.post(apiURL, body: requestBody, headers: headers);

      if(apiResult.statusCode == 200){
        apiResult.body;
      } else {
        Exception('gagal memuat data');
      }

      var jsonObject = json.decode(apiResult.body);
      //print(jsonObject);

      return PostResult.createPostResult(jsonObject);
    }
}

and this ui widget

class CheckBalance extends StatefulWidget {
  CheckBalanceState createState() => CheckBalanceState();
}

class CheckBalanceState extends State<CheckBalance> {
  PostResult postResult;

  @override
  Widget build(BuildContext context) {
    return new SafeArea(
        child: new Scaffold(
          appBar: BankMantapAppBar(),
          body: SingleChildScrollView(
            child: Padding(
              padding: const EdgeInsets.all(12.0),
              child: Column(
                children: <Widget>[
                  Row(
                    children: <Widget>[
                      RaisedButton(
                        onPressed: (){
                          PostResult.connectToAPI("0002104252033").then((value){
                            postResult = value;
                            setState(() {});
                          });
                        },
                        child: Text('CEK'),
                      ),
                    ],
                  ),
                  Card(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[

                        ListTile(
                          title: Text('nilai return'),
                          subtitle: Column(children: <Widget>[
                            Row(
                              children: <Widget>[
                                Text('response code : ', style: TextStyle(fontWeight: FontWeight.bold),),
                                Text((postResult != null)
                                    ? postResult.responseCode
                                    : "Tidak ada data",
                                  style: TextStyle(fontStyle: FontStyle.italic, fontSize: 15.0),
                                ),
                              ],
                            ),
                            Row(
                              children: <Widget>[
                                Text('return message : ', style: TextStyle(fontWeight: FontWeight.bold),),
                                Text((postResult != null)
                                    ? postResult.responseMessage
                                    : "Tidak ada data",
                                  style: TextStyle(fontStyle: FontStyle.italic, fontSize: 15.0),
                                ),
                              ],
                            ),
                            Row(
                              children: <Widget>[
                                Text('return tanggal : ', style: TextStyle(fontWeight: FontWeight.bold),),
                                Text((postResult != null)
                                    ? postResult.tanggal
                                    : "Tidak ada data",
                                  style: TextStyle(fontStyle: FontStyle.italic, fontSize: 15.0),
                                ),
                              ],
                            ),
                            Row(
                              children: <Widget>[
                                Text('return jam : ', style: TextStyle(fontWeight: FontWeight.bold),),
                                Text((postResult != null)
                                    ? postResult.jam
                                    : "Tidak ada data",
                                  style: TextStyle(fontStyle: FontStyle.italic, fontSize: 15.0),
                                ),
                              ],
                            ),
                            Row(
                              children: <Widget>[
                                Text('return nomorAccount : ', style: TextStyle(fontWeight: FontWeight.bold),),
                                Text((postResult != null)
                                    ? postResult.nomorAccount
                                    : "Tidak ada data",
                                  style: TextStyle(fontStyle: FontStyle.italic, fontSize: 15.0),
                                ),
                              ],
                            ),
                          ],),
                        ),
                      ],
                    ),
                  )
                ],
              ),
            ),
          ),
        )
    );
  }
}

this my error code

A non-null String must be provided to a Text widget.
'package:flutter/directory/widgets/text.dart':
Failed assertion: line 28510: 'data != null'

what I am trying to do is rather than giving values, I want it to take from the result of the POST request and display.
how to looping array POST request Result
Please your advice for my problem

3

There are 3 answers

3
Selim Kundakçıoğlu On BEST ANSWER

I guess you are trying to parse your json in a wrong way. And you can't get the variables in content. So they probably become null and your Text widget is trying to display a null object

{
  "responseCode": "0000",
  "responseMessage": "Success",
  "tanggal": "20200131",
  "jam": "112301",
  "content": [
    {
      "nomorAccount": "1234567890",
      "namaPegawai": "DEVELOPMENT",
      "statusAccount": "AKTIF",
      "jenisAccount": "TABUNGAN",
      "produkAccount": "GOLD",
      "mataUang": "IDR",
      "saldoEfektif": "+100055033221,84",
      "saldoBuku": "+100055058221,84"
    }
  ]
}

You are trying to get variables under content variable by calling directly like object['nomorAccount']. I would suggest you to create another model called Content

class Content {
  String nomorAccount;
  String namaPegawai;
  String statusAccount;
  String jenisAccount;
  String produkAccount;
  String mataUang;
  String saldoEfektif;
  String saldoBuku;

  Content({
    this.nomorAccount,
    this.namaPegawai,
    this.statusAccount,
    this.jenisAccount,
    this.produkAccount,
    this.mataUang,
    this.saldoEfektif,
    this.saldoBuku});

  factory Content.fromJson(Map<String, dynamic> json) {
    return Content (
      nomorAccount: json['nomorAccount'],
      namaPegawai: json['namaPegawai'],
      statusAccount: json['statusAccount'],
      jenisAccount: json['jenisAccount'],
      produkAccount: json['produkAccount'],
      mataUang: json['mataUang'],
      saldoEfektif:json['saldoEfektif'],
      saldoBuku:json['saldoBuku']
  );
}

And inside your PostResult model

class PostResult {
  String responseCode;
  String responseMessage;
  String tanggal;
  String jam;
  Content content;

  PostResult(
      {this.responseCode,
      this.responseMessage,
      this.tanggal,
      this.jam,
      this.content});

  factory PostResult.createPostResult(Map<String, dynamic> object) {
    return PostResult(
      responseCode: object['responseCode'],
      responseMessage: object['responseMessage'],
      tanggal: object['tanggal'],
      jam: object['jam'],
      content: Content.fromJson(object['content']),
    );
  }

  yourConnectToApiFunction()
}

EDIT:

I didn't realize that your JSON returns an array with only one item for content. If it always returns one item you can change your API to make it just an object instead of an array and leave the dart code as it is.

If in any case, it returns more than one object you need to change your model like below:

class PostResult {
  String responseCode;
  String responseMessage;
  String tanggal;
  String jam;
  List<Content> content;

  PostResult(
      {this.responseCode,
      this.responseMessage,
      this.tanggal,
      this.jam,
      this.content});

  factory PostResult.createPostResult(Map<String, dynamic> object) {
    return PostResult(
      responseCode: object['responseCode'],
      responseMessage: object['responseMessage'],
      tanggal: object['tanggal'],
      jam: object['jam'],
      content: (object['content'] as List)
          .map((e) => Content.fromJson(e as Map<String, dynamic>))
          .toList(),
    );
  }

  yourConnectToApiFunction()
}

And then you can get your item like responseObject.content[0].nomorAccount

Suggestion

Instead of hard coding all of this json classes I would suggest you to use Json Serializable package

1
vaibhav On

I think we need to follow JsonSerializable

3
Sagar Acharya On

check out the example below

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_sound_example/models.dart';

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

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

class _MyAppState extends State<MyApp> {
  List<Content> dataList = List();
  bool _isLoading = false;
  BuildContext context1;

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

  Future loadyourData() async {
    setState(() {
      _isLoading = true;
    });

// this is the local json that i have loaded from the assets folder
// you can make the http call here and else everything later is the same.

    String jsonString = await loadFromAssets();
    final content = contentFromJson(jsonString);
    dataList.add(content);

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

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

    loadyourData();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      body: _isLoading
          ? CircularProgressIndicator()
          : ListView.builder(
              itemCount: dataList.length,
              itemBuilder: (context, index) {
                return Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Card(
                    child: Column(
                      children: <Widget>[
                        // insert your tree accordingly
                        Text(dataList[index].tanggal),
                        Text(dataList[index].content[0].jenisAccount)
                      ],
                    ),
                  ),
                );
              },
            ),
    ));
  }
}

this is the main page above

// To parse this JSON data, do
//
//     final content = contentFromJson(jsonString);

import 'dart:convert';

Content contentFromJson(String str) => Content.fromJson(json.decode(str));

String contentToJson(Content data) => json.encode(data.toJson());

class Content {
  String responseCode;
  String responseMessage;
  String tanggal;
  String jam;
  List<ContentElement> content;

  Content({
    this.responseCode,
    this.responseMessage,
    this.tanggal,
    this.jam,
    this.content,
  });

  factory Content.fromJson(Map<String, dynamic> json) => Content(
        responseCode: json["responseCode"],
        responseMessage: json["responseMessage"],
        tanggal: json["tanggal"],
        jam: json["jam"],
        content: List<ContentElement>.from(
            json["content"].map((x) => ContentElement.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "responseCode": responseCode,
        "responseMessage": responseMessage,
        "tanggal": tanggal,
        "jam": jam,
        "content": List<dynamic>.from(content.map((x) => x.toJson())),
      };
}

class ContentElement {
  String nomorAccount;
  String namaPegawai;
  String statusAccount;
  String jenisAccount;
  String produkAccount;
  String mataUang;
  String saldoEfektif;
  String saldoBuku;

  ContentElement({
    this.nomorAccount,
    this.namaPegawai,
    this.statusAccount,
    this.jenisAccount,
    this.produkAccount,
    this.mataUang,
    this.saldoEfektif,
    this.saldoBuku,
  });

  factory ContentElement.fromJson(Map<String, dynamic> json) => ContentElement(
        nomorAccount: json["nomorAccount"],
        namaPegawai: json["namaPegawai"],
        statusAccount: json["statusAccount"],
        jenisAccount: json["jenisAccount"],
        produkAccount: json["produkAccount"],
        mataUang: json["mataUang"],
        saldoEfektif: json["saldoEfektif"],
        saldoBuku: json["saldoBuku"],
      );

  Map<String, dynamic> toJson() => {
        "nomorAccount": nomorAccount,
        "namaPegawai": namaPegawai,
        "statusAccount": statusAccount,
        "jenisAccount": jenisAccount,
        "produkAccount": produkAccount,
        "mataUang": mataUang,
        "saldoEfektif": saldoEfektif,
        "saldoBuku": saldoBuku,
      };
}

this is the model class you want.

{
    "responseCode": "0000",
    "responseMessage": "Success",
    "tanggal": "20200131",
    "jam": "112301",
    "content": [
      {
        "nomorAccount": "1234567890",
        "namaPegawai": "DEVELOPMENT",
        "statusAccount": "AKTIF",
        "jenisAccount": "TABUNGAN",
        "produkAccount": "GOLD",
        "mataUang": "IDR",
        "saldoEfektif": "+100055033221,84",
        "saldoBuku": "+100055058221,84"
      }
    ]
  }

this is the json i have loaded locally check out the example and let me know

Thanks.