snapshot.data имеет значение NULL. Я использую for l oop для перебора данных JSON и создания списка экземпляров объекта - PullRequest
2 голосов
/ 07 августа 2020

Я получаю данные json с json -generator.com и анализирую их, чтобы создать список компаний в приведенном ниже коде. Когда я печатаю переменную JsonData, я вижу данные, но snapshot.data имеет значение null. вот мой код

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

class Companies extends StatefulWidget {
  @override
  _CompaniesState createState() => _CompaniesState();
}

class _CompaniesState extends State<Companies> {
  Future<List<Company>> _getCompanies() async {
    var data = await http.get("http://www.json-generator.com/api/json/get/bUYmnsimgi?indent=2");
    var jsonData = json.decode(data.body);

    List<Company> companies = [];
    for (var c in jsonData) {
      Company company = Company(
          c["name"],
          c["opportunites"],
          c["address"],
          c["city"],
          c["state"],
          c["country"],
          c["zipcode"],
          c["phone"],
          c["timezone"],
          c["pipelineRevenue"],
          c["revenueAchieved"],
          c["tags"]);
      companies.add(company);
    }
    return companies;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: FutureBuilder(
            future: _getCompanies(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.hasData) {
                return ListView.builder(
                    itemCount: snapshot.data.length,
                    itemBuilder: (BuildContext context, int index) {
                      return CompanyCardStyle(company: snapshot.data[index]);
                    });
              } else {
                return Center(
                  child: CircularProgressIndicator(),
                );
              }
            }));
  }
}

Вот объект моей компании

class Company {
  String name;
  String address;
  int opportunities;
  int pipelineRevenue;
  int revenueAchieved;
  String city;
  String state;
  String country;
  int zipcode;
  double phone;
  String timezone;
  String tags;

  Company(
      this.name,
      this.address,
      this.opportunities,
      this.pipelineRevenue,
      this.revenueAchieved,
      this.city,
      this.state,
      this.country,
      this.zipcode,
      this.phone,
      this.timezone,
      this.tags);
}

Я думаю, что есть проблема с l oop, но я не могу понять, что не так Я новичок для такого анализа данных.

Ответы [ 3 ]

1 голос
/ 07 августа 2020

Я просмотрел веб-сайт и заметил, что у вас были неправильные типы. Например, теги - это список , но вы помещаете его как String . То же самое и с номером телефона , он должен быть String, а не двойным. И поскольку вы не используете именованные параметры , вам нужно будет разместить свои свойства из конструктора в порядке тот же всякий раз, когда вы создаете экземпляр этого класса.

class Company {
  String name;
  String address;
  int opportunities;
  int pipelineRevenue;
  int revenueAchieved;
  String city;
  String state;
  String country;
  int zipcode;
  String phone;
  String timezone;
  List tags;

  Company(
    this.name,
    this.opportunities,
    this.address,
    this.city,
    this.state,
    this.country,
    this.zipcode,
    this.phone,
    this.timezone,
    this.pipelineRevenue,
    this.revenueAchieved,
    this.tags);
}
1 голос
/ 07 августа 2020

Это потому, что FutureBuilder возвращает событие Error. Вы можете проверить, что это за ошибка, набрав snapshot.error (или snapshot.hasError, чтобы проверить, есть ли какие-либо ошибки).

Когда я попробовал ваш код, появилось сообщение Expected a value of type 'int', but got one of type 'String'. Похоже, это проблема, когда вы создаете экземпляр объекта Company. Некоторым свойствам (например, opportunities) требуется int, но вы указываете его в String, потому что значение в декодированном json - String. Сначала вам нужно разобрать его на int.

0 голосов
/ 07 августа 2020

Вы что-то делали неправильно:

  1. Некоторым полям, исходящим от конечной точки, были присвоены неправильные data type (номер телефона требовал String, но вы использовали double. tags также возвращает List, но вы использовали String.

  2. Вы поменяли местами большинство полей конструктора друг с другом при преобразовании jsonData в объект Company.

Решение:

  1. Сделайте конструктор фабрики для вашего класса Company, который упрощает десериализацию json. проверьте официальную документацию для примера.
  2. Используйте правильные типы данных для каждого из ваших полей.

Примечание: я сделал поле tag String и доступ только к первому элементу в списке из API.

КЛАСС КОМПАНИИ

class Company {
  String name;
  String address;
  int opportunities;
  int pipelineRevenue;
  int revenueAchieved;
  String city;
  String state;
  String country;
  int zipcode;
  String phone;
  String timezone;
  String tags;

  Company(
      this.name,
      this.address,
      this.opportunities,
      this.pipelineRevenue,
      this.revenueAchieved,
      this.city,
      this.state,
      this.country,
      this.zipcode,
      this.phone,
      this.timezone,
      this.tags);

  // make a constructor for converting json to a company object
  factory Company.fromJson(Map<String, dynamic> json) {
    return Company(
      json["name"],
      json["address"],
      json["opportunities"],
      json["pipelineRevenue"],
      json["revenueAchieved"],
      json["city"],
      json["state"],
      json["country"],
      json["zipcode"],
      json["phone"],
      json["timezone"],
      json["tags"][0],
    );
  }
}
  • ВИДЖЕТ КОМПАНИИ *
class Companies extends StatefulWidget {
  @override
  _CompaniesState createState() => _CompaniesState();
}

class _CompaniesState extends State<Companies> {
  Future<List<Company>> _getCompanies() async {
    var data = await http
        .get("http://www.json-generator.com/api/json/get/bUYmnsimgi?indent=2");
    var jsonData = json.decode(data.body) as List;
    List<Company> companies = [];
    // convert the json to a list of companies
    companies = jsonData
        .map((company) => Company.fromJson(company))
        .toList(); // new line
    print(companies.length);
    return companies;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          child: FutureBuilder(
              future: _getCompanies(),
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                if (snapshot.hasData) {
                  return ListView.builder(
                      itemCount: snapshot.data.length,
                      itemBuilder: (BuildContext context, int index) {
                        // use your company card here
                        return Text(
                            'Company $index name: ${snapshot.data[index].name}');
                      });
                } else {
                  return Center(
                    child: CircularProgressIndicator(),
                  );
                }
              })),
    );
  }
}

вывод

...