How do I list data from a model that receives a JSON but an array in the structure?

Asked

Viewed 200 times

0

The goal here is to list the array tracking, but it presents this error below when I try:

ERROR:

Exception has occurred. Nosuchmethoderror (Nosuchmethoderror: The method '[]' was called on null.

REPOSITORY: GIT HUB files

JSON:

{
   "success":true,
   "message":"Documento localizado com sucesso",
   "header":{
      "remetente":"REMETENTE AQUI",
      "destinatario":"Nome do Destinatario",
      "comprovante":"https://ssw.inf.br/app/ssw0637?sigla=XXX&s=1356359&img=47594E34323431383836"
   },
   "tracking":[
      {
         "data_hora":"2020-03-26T22:12:36",
         "dominio":"XXX",
         "filial":"GYN",
         "cidade":"GOIANIA / GO",
         "ocorrencia":"MERCADORIA RECEBIDA PARA TRANSPORTE (80)",
         "descricao":"Redespacho autorizado com 1 volume e 0 Kg. Destino: GO/ARAGARCAS. Previsao de entrega: 27/03/20.",
         "tipo":"Informativo",
         "data_hora_efetiva":"2020-03-26T22:12:36",
         "nome_recebedor":"",
         "nro_doc_recebedor":""
      },
      {
         "data_hora":"2020-03-26T22:55:47",
         "dominio":"XXX",
         "filial":"GYN",
         "cidade":"GOIANIA / GO",
         "ocorrencia":"SAIDA DE UNIDADE (82)",
         "descricao":"Saida da unidade GOIANIA em 26/03/20, 22:55h. Previsao de chegada na unidade ARAGARCAS em 27/03/20, 07:00h.",
         "tipo":"Informativo",
         "data_hora_efetiva":"2020-03-26T22:55:43",
         "nome_recebedor":"",
         "nro_doc_recebedor":""
      }

   ]
}

Model: tracking.Dart

class Tracking {
//  final String tracking;
  final DateTime data_hora;
  final String dominio;
  final String filial;
  final String cidade;
  final String descricao;
  final String tipo;
  final DateTime data_hora_efetiva;
  final String nome_recebedor;
  final String nro_doc_recebedor;

  final String ocorrencia;

  Tracking({
    this.data_hora,
    this.dominio,
    this.filial,
    this.cidade,
    this.ocorrencia,
    this.descricao,
    this.tipo,
    this.data_hora_efetiva,
    this.nome_recebedor,
    this.nro_doc_recebedor,
  });

  factory Tracking.fromJson(Map<String, dynamic> json) {
    return Tracking(
      data_hora: json['tracking']['data_hora'],
      dominio: json['tracking']['dominio'],
      filial: json['tracking']['filial'],
      cidade: json['tracking']['cidade'],
      ocorrencia: json['tracking']['ocorrencia'],
      descricao: json['tracking']['descricao'],
      tipo: json['tracking']['tipo'],
      data_hora_efetiva: json['tracking']['data_hora_efetiva'],
      nome_recebedor: json['tracking']['nome_recebedor'],
      nro_doc_recebedor: json['tracking']['nro_doc_recebedor'],
    );
  }

}

Widget:

  import 'dart:convert';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:luz_transportes/models/rastreio.dart';
import 'package:luz_transportes/models/tracking.dart';

class Result extends StatelessWidget {
  final String cnpj;
  final String senha;
  final String nronf;
  final String pedido;
  final String url;

  Result({Key key, this.cnpj, this.senha, this.nronf, this.pedido, this.url})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Resultado do Rastreamento'),
        backgroundColor: Colors.lightGreen,
      ),
      body: FutureBuilder<List<Tracking>>(
          future: fetchTracking(),
          builder: (context, snapshot) {
            if (snapshot.connectionState != ConnectionState.done) {
              // return: show loading widget
            }
            if (snapshot.hasError) {
              // return: show error widget
            }
            List<Tracking> tracking = snapshot.data ?? [];
            return ListView.builder(
                itemCount: tracking.length,
                itemBuilder: (context, index) {
                  Tracking track = tracking[index];
                  return new Text(track.cidade);
                });
          }),
    );
  }

  Future<Rastreio> _dados() async {
    var response = await http.post(Uri.encodeFull("$url"),
        body: json.encode({
          "cnpj": "$cnpj".replaceAll(new RegExp(r'[^\w\s]+'), ''),
          "senha": "$senha",
          "nro_nf": "$nronf",
          //"pedido": "$pedido}",
        }),
        headers: {
          "content-type": "application/json",
        });

    if (response.statusCode == 200) {
      print(response.body);
      return Rastreio.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to load tracking');
    }
  }

  Future<List<Tracking>> fetchTracking() async {
    var response = await http.post(Uri.encodeFull("$url"),
        body: json.encode({
          "cnpj": "$cnpj".replaceAll(new RegExp(r'[^\w\s]+'), ''),
          "senha": "$senha",
          "nro_nf": "$nronf",
          //"pedido": "$pedido",
        }),
        headers: {
          "content-type": "application/json",
        });

    if (response.statusCode == 200) {
      var dados = jsonDecode(response.body);

      print(response.body);
      final trackingListJson = (dados["tracking"] as List);
      final trackingListModel = List<Tracking>();

      for (var item in trackingListJson)
        trackingListModel.add(Tracking.fromJson(item));

      return trackingListModel;
    } else {
      throw Exception('Failed to load tracking');
    }
  }
}

1 answer

1


To work with an array of your Model type, you will have to deserialize the data in a list and then throw each record inside your model.

A necessary change is in your Model... Since she is a Model, let her do only her job, then remove the key ['tracking'], it is interesting to let the screen already send only the necessary part:

  factory Tracking.fromJson(Map<String, dynamic> json) {
    return Tracking(
      data_hora: json['data_hora'],
      dominio: json['dominio'],
      filial: json['filial'],
      cidade: json['cidade'],
      ocorrencia: json['ocorrencia'],
      descricao: json['descricao'],
      tipo: json['tipo'],
      data_hora_efetiva: json['data_hora_efetiva'],
      nome_recebedor: json['nome_recebedor'],
      nro_doc_recebedor: json['nro_doc_recebedor'],
    );
  }

Another change is the following, change your method fetchTracking() as follows:

Future<List<Tracking>> fetchTracking() async {
  var response = await http.post(Uri.encodeFull("$url"),
      body: json.encode({
        "cnpj": "$cnpj".replaceAll(new RegExp(r'[^\w\s]+'), ''),
        "senha": "$senha",
        "nro_nf": "$nronf",
        //"pedido": "$pedido",
      }),
      headers: {
        "content-type": "application/json",
      });

  if (response.statusCode == 200) {
    var dados = jsonDecode(response.body);
    final trackingListJson = (dados["tracking"] as List);
    final trackingListModel = List<Tracking>();

   for (var item in trackingListJson)   
  trackingListModel.add(Tracking.fromJson(item));

    return trackingListModel;
  } else {
    throw Exception('Failed to load tracking');
  }
}

This way the method will return a list of type List<Tracking> then you will have to make the necessary adjustments where you will receive the return of this method!

You can read a little more about JSON on Flutter here in this story I created on Medium

Uncomplicating the JSON on Flutter

  • Legal Matheus, however, is presenting error in iterating/listing this model return there in the widget.

  • 1

    I settled here, thank you!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.