When retrieving api's values I get "_TypeError (type 'Null' is not a subtype of type 'String')"

Viewed 52

I'm trying to retrieve the data from this API: https://www.bkgchallenge.it/badmin/APIM/getsquadre.php

But I receive the exception _TypeError (type 'Null' is not a subtype of type 'String'). I suppose that the program can't retrieve values from the JSON file correctly.

The code is the following:

Edit 1.0:

I tried to make strings nullable or declare them as "final dynamic" but I get the same error in another part of the code: Error

I don't know at this point if it's a problem with the API, but on Postman I visualize the data correctly.

Edit 1.1:

This is the result of my API in postman: Api Result

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

Future<Squadre> fetchAlbum() async {
  final response = await http
      .get(Uri.parse('https://www.bkgchallenge.it/badmin/APIM/getsquadre.php'));

  if (response.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.
    return Squadre.fromJson(jsonDecode(response.body));
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Non sono riuscito a decodificare le squadre');
  }
}

class Squadre {
  final String squId;
  final String squNome;
  final String squStagione;
  final String squ1Allenatore;
  final String squ2Allenatore;

  const Squadre({
    required this.squId,
    required this.squNome,
    required this.squStagione,
    required this.squ1Allenatore,
    required this.squ2Allenatore,
  });

  factory Squadre.fromJson(Map<String, dynamic> json) {
    return Squadre(
      squId: json['squ_id'],
      squNome: json['squ_nome'],
      squStagione: json['squ_stagione'],
      squ1Allenatore: json['squ_1allenatore'],
      squ2Allenatore: json['squ_2allenatore'],
    );
  }
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: QuoteList(),
    );
  }
}

class QuoteList extends StatefulWidget {
  const QuoteList({super.key});

  @override
  State<QuoteList> createState() => _QuoteListState();
}

class _QuoteListState extends State<QuoteList> {
  late Future<Squadre> futureAlbum;

  @override
  void initState() {
    super.initState();
    futureAlbum = fetchAlbum();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fetch Data Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Lista'),
        ),
        body: Center(
          child: FutureBuilder<Squadre>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data!.squNome);
              } else if (snapshot.hasError) {
                return Text('${snapshot.error}');
              }

              // By default, show a loading spinner.
              return const CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}
2 Answers

The problem is that the API returns a list in the data property but the code is trying to convert the entire response JSON into a Squadre object instead of a list of Squadres.

Try the following instead. Check the changes in fetchAlbum.

Screenshot

import 'dart:convert';

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

Future<List<Squadre>> fetchAlbum() async {
  final response = await http
      .get(Uri.parse('https://www.bkgchallenge.it/badmin/APIM/getsquadre.php'));

  if (response.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.
    return (jsonDecode(response.body)['data'] as List<dynamic>)
        .map((json) => Squadre.fromJson(json))
        .toList();
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Non sono riuscito a decodificare le squadre');
  }
}

class Squadre {
  final String squId;
  final String squNome;
  final String squStagione;
  final String squ1Allenatore;
  final String squ2Allenatore;

  const Squadre({
    required this.squId,
    required this.squNome,
    required this.squStagione,
    required this.squ1Allenatore,
    required this.squ2Allenatore,
  });

  factory Squadre.fromJson(Map<String, dynamic> json) {
    return Squadre(
      squId: json['squ_id'],
      squNome: json['squ_nome'],
      squStagione: json['squ_stagione'],
      squ1Allenatore: json['squ_1allenatore'],
      squ2Allenatore: json['squ_2allenatore'],
    );
  }
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: QuoteList(),
    );
  }
}

class QuoteList extends StatefulWidget {
  const QuoteList({super.key});

  @override
  State<QuoteList> createState() => _QuoteListState();
}

class _QuoteListState extends State<QuoteList> {
  late Future<List<Squadre>> futureAlbum;

  @override
  void initState() {
    super.initState();
    futureAlbum = fetchAlbum();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fetch Data Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Lista'),
        ),
        body: Center(
          child: FutureBuilder<List<Squadre>>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasError) {
                return Text('${snapshot.error}');
              }

              if (snapshot.data == null) {
                return const CircularProgressIndicator();
              }

              return ListView.separated(
                itemBuilder: (context, index) =>
                    Text(snapshot.data![index].squNome),
                separatorBuilder: (context, index) => const Divider(),
                itemCount: snapshot.data!.length,
              );
            },
          ),
        ),
      ),
    );
  }
}
class Squadre {
  final dynamic squId;
  final dynamic squNome;
  final dynamic squStagione;
  final dynamic squ1Allenatore;
  final dynamic squ2Allenatore;

  const Squadre({
    required this.squId,
    required this.squNome,
    required this.squStagione,
    required this.squ1Allenatore,
    required this.squ2Allenatore,
  });

  factory Squadre.fromJson(Map<String, dynamic> json) {
    return Squadre(
      squId: json['squ_id'],
      squNome: json['squ_nome'],
      squStagione: json['squ_stagione'],
      squ1Allenatore: json['squ_1allenatore'],
      squ2Allenatore: json['squ_2allenatore'],
    );
  }
}
Related