I am trying to print API data from Earthquakes for a school project but it gives me an error:
type 'null' is not a subtype of type 'map string dynamic '.
How to fix this? API is working btw. Here is my code:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Album> createAlbum(String events) async {
final response = await http.get(Uri.parse('https://cdn.knmi.nl/knmi/map/page/seismologie/all_induced.json')); // url api
if (response.statusCode == 200) {
// status code moet 200 zijn om uit te printen.
print(response.body); // in de console word alle data geprint
final json = jsonDecode(response.body);
return Album.fromJson(json[0]);
} else {
throw Exception(response.statusCode.toString()); // status code word geprint als het niet gelijk is aan 200
}
}
class Album {
final String events;
Album({required this.events});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
events: json['events'] as String, // variable fact word gepakt om uit te printen
// place: json['[place]'],
// generated: json['generated'],
// coordinates: json['coordinates'],
);
}
}
void main() {
runApp(const MaterialApp(
title: 'Test', // class om een titel aan te maken in de appbar
home: FirstRoute(),
));
}
class FirstRoute extends StatefulWidget {
const FirstRoute({Key? key}) : super(key: key);
@override
_MyAppState createState() {
return _MyAppState();
}
}
class _MyAppState extends State<FirstRoute> {
final TextEditingController _controller = TextEditingController();
Future <Album>? _futureAlbum;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Honden Feiten',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Honden Feiten'),
),
body: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(9.0),
child: (_futureAlbum== null ) ? buildColumn() : buildFutureBuilder(),
),
),
);
}
Column buildColumn() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network('https://e7.pngegg.com/pngimages/496/352/png-clipart-osaka-earthquake-computer-icons-earthquake-engineering-earthquakes-text-logo-thumbnail.png'),
ElevatedButton( // knop met de future album word geprint
onPressed: () {
setState(() {
_futureAlbum = createAlbum(_controller.text); // de class wordt geprint waar de variable van de API in staan.
});
},
child: const Text('Klik hier voor een honden feitje! (in het engels)'),
),
],
);
}
// error code of niet
FutureBuilder<Album> buildFutureBuilder() {
return FutureBuilder<Album>(
future: _futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.events );
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
}
}
CodePudding user response:
https://github.com/Lavkushwaha/StackOverFlow_Student
First you don't need index in json[0]
its not list so you can directly use as
: line number 14
return Album.fromJson(json[0]);
then you will error in : line number 31
_CastError (type 'List<dynamic>' is not a subtype of type 'String' in type cast)
cause events is list not string, and you are trying to Map it as string.
ill tell you simple solution
Copy json response from API, go to QuickType -> select dart, create dart model for it
In the success response directly cast model with your json response;
then you can access it in your app
let me know if you need anything else.
Thanks
Added Working code for your project
https://github.com/Lavkushwaha/StackOverFlow_Student
just create a file earthquake.model.dart paste it
now in line number 14 change final earthquake = earthquakeFromJson(jsonString);
// To parse this JSON data, do
//
// final earthquake = earthquakeFromJson(jsonString);
import 'dart:convert';
Earthquake earthquakeFromJson(String str) => Earthquake.fromJson(json.decode(str));
String earthquakeToJson(Earthquake data) => json.encode(data.toJson());
class Earthquake {
Earthquake({
this.events,
});
final List<Event> events;
factory Earthquake.fromJson(Map<String, dynamic> json) => Earthquake(
events: json["events"] == null ? null : List<Event>.from(json["events"].map((x) => Event.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"events": events == null ? null : List<dynamic>.from(events.map((x) => x.toJson())),
};
}
class Event {
Event({
this.date,
this.depth,
this.evaluationMode,
this.lat,
this.lon,
this.mag,
this.place,
this.time,
this.type,
});
final DateTime date;
final String depth;
final EvaluationMode evaluationMode;
final String lat;
final String lon;
final String mag;
final String place;
final String time;
final Type type;
factory Event.fromJson(Map<String, dynamic> json) => Event(
date: json["date"] == null ? null : DateTime.parse(json["date"]),
depth: json["depth"] == null ? null : json["depth"],
evaluationMode: json["evaluationMode"] == null ? null : evaluationModeValues.map[json["evaluationMode"]],
lat: json["lat"] == null ? null : json["lat"],
lon: json["lon"] == null ? null : json["lon"],
mag: json["mag"] == null ? null : json["mag"],
place: json["place"] == null ? null : json["place"],
time: json["time"] == null ? null : json["time"],
type: json["type"] == null ? null : typeValues.map[json["type"]],
);
Map<String, dynamic> toJson() => {
"date": date == null ? null : "${date.year.toString().padLeft(4, '0')}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}",
"depth": depth == null ? null : depth,
"evaluationMode": evaluationMode == null ? null : evaluationModeValues.reverse[evaluationMode],
"lat": lat == null ? null : lat,
"lon": lon == null ? null : lon,
"mag": mag == null ? null : mag,
"place": place == null ? null : place,
"time": time == null ? null : time,
"type": type == null ? null : typeValues.reverse[type],
};
}
enum EvaluationMode { MANUAL }
final evaluationModeValues = EnumValues({
"manual": EvaluationMode.MANUAL
});
enum Type { INDUCED_EARTHQUAKE }
final typeValues = EnumValues({
"induced earthquake": Type.INDUCED_EARTHQUAKE
});
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}