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();