Home > Mobile >  How to solve value of type 'Map<String, dynamic>', but got one of type 'List<
How to solve value of type 'Map<String, dynamic>', but got one of type 'List<

Time:08-10

I want to get an image from an api and I get the error mentioned in the title.

class _ApiState extends State<Api> {
  Future<CatData> fetchcat() async {
    final response =
        await http.get(Uri.parse('https://api.thecatapi.com/v1/images/search'));

    // Appropriate action depending upon the
    // server response
    if (response.statusCode == 200) {
      return CatData.fromJson(json.decode(response.body));
      //return CatData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
    } else {
      throw Exception('Failed to load album');
    }
  }

  late Future<CatData> futureAlbum;

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

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<CatData>(
      future: fetchcat(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Image.network(snapshot.data!.imagen);
        } else if (snapshot.hasError) {
          return Text("${snapshot.error}");
        }
        return CircularProgressIndicator();
      },
    );
  }
}

here the class model

class CatData {
  String imagen;

  CatData({required this.imagen});

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

If I get an answer please, I would like you to explain to me the reason for the problem. because i always get this kind of errors when i consume apis. "receives one value but expects another"

https://api.thecatapi.com/v1/images/search

CodePudding user response:

Well, json.decode(response.body) gives you back a List<dynamic>, but you declared the method fromJson to accept one argument of type Map<String, dynamic>, thus the incompatibility. You can change the signature of the method fromJson and set it to List<dynamic>. Then you could access it with json[0].url, json[0]['url'] or {url} = json[0]. I tested the following code in https://dartpad.dev and works like a charm now.

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

Future<CatData> fetchcat() async {
    final response =
        await http.get(Uri.parse('https://api.thecatapi.com/v1/images/search'));

    // Appropriate action depending upon the
    // server response
    if (response.statusCode == 200) {
      return CatData.fromJson(json.decode(response.body));
      //return CatData.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
    } else {
      throw Exception('Failed to load album');
    }
}

class CatData {
  String imagen;

  CatData({required this.imagen});

  factory CatData.fromJson(List<dynamic> json) {
    return CatData(
      imagen: json[0]['url']
    );
  }
}

void main() async {
  CatData catData = await fetchcat();
  print(catData.imagen);
}

CodePudding user response:

You probably making mistake on casting. first make sure what kind of data you are retrieving means is it key-value pair { "url" : "www...." } or List [{"url" :"www...} , { "url": " www..."}]

if its key-value pairs then decode it as follows:

final decoded = json.decode(response.body) as Map<String, dynamic>;
final _catData = CataData.fromJson(decoded);

or if its list of urls then do it as follows:

final _decoded = json.decode(response.body) as List<dynamic>;
final _catsData = _decoded.map((e) => CatData.fromJson(e as Map<String, dynamic>)).toList();
  • Related