Home > Blockchain >  type 'Null' is not a subtype of type 'String' Flutter
type 'Null' is not a subtype of type 'String' Flutter

Time:09-21

I'm trying to get currency conversion data from an API ("https://api.exchangerate.host/latest").

The above error in the title is shown on the screen as a text.

I'm trying to get this message as the output.

"msg":"If you or your company use this project or like what we doing, please consider backing us so we can continue maintaining and evolving this project."

Later the individual currency rates.

import 'dart:async';
import 'dart:convert';

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

Future<Album> fetchAlbum() async {
  final response = await http.get(Uri.parse('https://api.exchangerate.host/latest'));

  if (response.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.
    return Album.fromJson(jsonDecode(response.body));
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  }
}

class Album {
  final String msg;

  Album({
    required this.msg,
  });

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      msg: json['msg'],
    );
  }
}

class CurrencyPage extends StatefulWidget {
  const CurrencyPage({Key? key}) : super(key: key);

  @override
  _CurrencyPageState createState() => _CurrencyPageState();
}

class _CurrencyPageState extends State<CurrencyPage> {
  late Future<Album> 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('Fetch Data Example'),
        ),
        body: Center(
          child: FutureBuilder<Album>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data!.msg);
              } else if (snapshot.hasError) {
                return Text('${snapshot.error}');
              }

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

Any help would be appreciated!

CodePudding user response:

you are using the model incorrectly. change return Album.fromJson(jsonDecode(response.body)); to return jsonDecode(response.body); and get response data like snapshot.data!['motd']

code:

Future<dynamic> fetchAlbum() async {
  final response = await http.get(Uri.parse('https://api.exchangerate.host/latest'));

  if (response.statusCode == 200) {

    // If the server did return a 200 OK response,
    // then parse the JSON.
    print(jsonDecode(response.body));
    return jsonDecode(response.body);
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  }
}

class Album {
  final String msg;

  Album({
    required this.msg,
  });

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      msg: json['msg'],
    );
  }
}

class CurrencyPage extends StatefulWidget {
  const CurrencyPage({Key? key}) : super(key: key);

  @override
  _CurrencyPageState createState() => _CurrencyPageState();
}

class _CurrencyPageState extends State<CurrencyPage> {
  late dynamic futureAlbum;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Fetch Data Example'),
        ),
        body: Center(
          child: FutureBuilder<dynamic>(
            future: futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data!['motd']['msg']);
              } else if (snapshot.hasError) {
                return Text('${snapshot.error}');
              }

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

CodePudding user response:

msg key is inside motd object in response. Therefore replace fetchAlbum with this:

Future<Album> fetchAlbum() async {
  final response = await http.get(Uri.parse('https://api.exchangerate.host/latest'));

  if (response.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.
    var body = jsonDecode(response.body);
    
    return Album.fromJson(body["motd"]);
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load album');
  }
}
  • Related