Error in flutter: type 'String' is not a subtype of type 'int' of 'index'

Viewed 30

I want to display a list from API and I get the error 'type 'String' is not a subtype of type 'int' of 'index''. I've seen all the same questions and I've tried everthing but I keep having the same error. Any help will be much appreciated!

Here is my code:

final List<Team> _teams = <Team>[];

Future<List<Team>> getTeams() async {
  final response = await http
      .get(Uri.parse('http://...'), headers: {
    'Authorization': 'Basic ...',
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  });
  print('Response status: ${response.statusCode}');
  print('Response body: ${response.body}');

  if (response.statusCode == 200) {
    List<Team> model = List<Team>.from(
        json.decode(response.body)['data'].map((x) => Team.fromJson(x)));
    return model;
  } else {
    throw Exception('error occured');
  }
}

class TeamsScreen extends StatefulWidget {

  const TeamsScreen({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _TeamsScreenState();
}

class _TeamsScreenState extends State<TeamsScreen> {
  late Future<List<Team>> futureTeam;
  late SharedPreferences logindata;
  String? username;

  @override
  void initState() {
    super.initState();
    initial();
    futureTeam = getTeams();
  }

  void initial() async {
    logindata = await SharedPreferences.getInstance();
    setState(() {
      username = logindata.getString('username') ?? '';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: const Color(0Xfff7f7f5),
        appBar: AppBar(
          centerTitle: false,
          leadingWidth: 0,
          backgroundColor: Colors.white,
          toolbarHeight: 60.0,
          title: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              const Text(
                '...',
                style: TextStyle(
                  color: Colors.black,
                  fontFamily: 'Cera',
                  fontWeight: FontWeight.bold,
                  fontSize: 18,
                ),
              ),
              Text(
                '...',
                textAlign: TextAlign.left,
                style: const TextStyle(
                  color: Colors.grey,
                  fontFamily: 'Cera',
                  fontSize: 12,
                ),
              )
            ],
          ),
        ),
        body: Container(
          padding: const EdgeInsets.only(
            top: 25,
            left: 5,
          ),
          child: FutureBuilder<List<Team>>(
            future: futureTeam,
            builder: (context, AsyncSnapshot snapshot) {
              if (snapshot.hasData) {
                // var team = (snapshot.data as List<Team>).toList();
                List<Team> team = snapshot.data;
                return ListView.builder(
                    shrinkWrap: true,
                    physics: const ClampingScrollPhysics(),
                    padding: const EdgeInsets.only(
                      top: 25,
                      left: 5,
                    ),
                    itemCount: team.length, //+1
                    itemBuilder: (BuildContext context, int index) {
                      return TeamWidget(_teams[index], (() {
                        onTeamTap(context, index);
                      }));
                    });
              } else if (snapshot.hasError) {
                logger.e('${snapshot.error}');
              }
              return const Center(
                child: CircularProgressIndicator.adaptive(),
              );
            },
          ),
        ));
  }

  onTeamTap(BuildContext context, int index) {
    Navigator.push(context,
        MaterialPageRoute(builder: (context) => AthleteScreen(_teams[index])));
  }
}

The Team model:

class Team {
  List<Team> teamFromJson(String str) =>
      List<Team>.from(json.decode(str).map((x) => Team.fromJson(x)));
  String teamToJson(List<Team> data) =>
      json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

  final TeamKey teamKey;
  final String teamName;
  final int hidden;
  final User user;
  final String depName;

  Team(
      {required this.teamKey,
      required this.teamName,
      required this.hidden,
      required this.user,
      required this.depName});

  factory Team.fromJson(Map<String, dynamic> json) => Team(
        teamKey: TeamKey.fromJson(json['teamKey']),
        teamName: json['teamName'] as String,
        hidden: int.parse(json['hidden']),
        user: User.fromJson(json['user']),
        depName: json['depName'] as String,
      );

  Map<String, dynamic> toJson() => {
        'teamKey': teamKey,
        'teamName': teamName,
        'hidden': hidden.toString(),
        'user': user,
        'depName': depName,
      };
}

And the response body from Postman:

[
    {
        "teamKey": {
            "depId": 1,
            "teamId": 1
        },
        "teamName": "..",
        "hidden": 0,
        "user": {
            "id": 1,
            "username": "...",
            "role": "..."
        },
        "depName": "..."
    }
]
1 Answers

Change this:

if (response.statusCode == 200) {
    List<Team> model = List<Team>.from(
        json.decode(response.body)['data'].map((x) => Team.fromJson(x)));
    return model;
  } else {
    throw Exception('error occured');
  }

to:

if (response.statusCode == 200) {
      var tempList = json.decode(response.body);

      List<Team> model = tempList.map((e) => Team.fromJson(e)).toList();

      return model;
    } else {
      throw Exception('error occured');
    }

and also in your fromJson change:

hidden: int.parse(json['hidden']),

to:

hidden: json['hidden'] as int,

You don't need to parse the int value to int; you already get it as int from api. Also do this in other class model with other int parsing.

Related