I convert the JSON file to dart using a quiqtype generator when a consume a simple object they work fine but when I want to consume a list inside an object I get many errors ('type null is not subtyped of type Map<string, dynamic>")
this is the JSON file
[{"id":48,"name":"Golf 7 DG-382-ED","status":"offline","position":null,"vehicleId":245,"driver":null,"motionState":"untracked","motionTime":null,"immobileFeature":false,"geofenceIds":null,"deviceState":null},{"id":136,"name":"GOLF 7 FJ-468-TH","status":"online","position":{"fixTime":"2022-02-21T08:51:40.000 00:00","speed":0.0,"bearing":0.0,"address":"51 Rue de Verdun, Suresnes, Île-de-France","latlng":[48.8734666,2.2296383],"attributes":{"alarm":null,"immobile":null,"odometer":1.2178792E7,"fuelUsed":1195.45,"avgFuelUsed":6.48,"ignition":false,"coolantTemp":0.0,"power":12.51,"battery":3.96}},"vehicleId":307,"driver":{"name":"Jalloul KAROUIA","phone":"0033615275389"},"motionState":"parked","motionTime":"2022-02-21T08:51:40.000 00:00","immobileFeature":false,"geofenceIds":[],"deviceState":{"parkingAddress":"51 Rue de Verdun, Suresnes, Île-de-France","tracks":[],"traveldistance":0.0,"travelingDuration":0}}]
and this is the dart file
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:convert';
Future<List<Vehicle>> fetchVehicle() async {
final response = await http.get(
Uri.parse(''),
headers: {
"Authorization":
""
},
);
if (response.statusCode == 200) {
final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
return parsed.map<Vehicle>((json) => Vehicle.fromJson(json)).toList();
} else {
throw Exception('Failed to load album');
}
}
List<Vehicle> vehicleFromJson(String str) =>
List<Vehicle>.from(json.decode(str).map((x) => Vehicle.fromJson(x)));
class Vehicle {
Vehicle({
required this.id,
required this.name,
required this.status,
required this.position,
required this.vehicleId,
required this.driver,
required this.motionState,
required this.motionTime,
required this.immobileFeature,
required this.geofenceIds,
required this.deviceState,
});
int id;
String name;
String status;
Position position;
int vehicleId;
Driver driver;
String motionState;
DateTime motionTime;
bool immobileFeature;
List<dynamic> geofenceIds;
DeviceState deviceState;
factory Vehicle.fromJson(Map<String, dynamic> json) => Vehicle(
id: json["id"],
name: json["name"],
status: json["status"],
position: Position.fromJson(json["position"]),
vehicleId: json["vehicleId"],
driver: Driver.fromJson(json["driver"]),
motionState: json["motionState"],
motionTime: json["motionTime"] ?? new DateTime(2022, 12, 11),
immobileFeature: json["immobileFeature"],
geofenceIds: json["geofenceIds"] ?? [],
deviceState: DeviceState.fromJson(json["deviceState"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"status": status,
"position": position.toJson(),
"vehicleId": vehicleId,
"driver": driver.toJson(),
"motionState": motionState,
"motionTime": motionTime.toIso8601String(),
"immobileFeature": immobileFeature,
"geofenceIds": List<dynamic>.from(geofenceIds.map((x) => x)),
"deviceState": deviceState.toJson(),
};
}
class DeviceState {
DeviceState({
required this.parkingAddress,
required this.tracks,
required this.traveldistance,
required this.travelingDuration,
});
String parkingAddress;
List<dynamic> tracks;
int traveldistance;
int travelingDuration;
factory DeviceState.fromJson(Map<String, dynamic> json) => DeviceState(
parkingAddress: json["parkingAddress"],
tracks: List<dynamic>.from(json["tracks"].map((x) => x)),
traveldistance: json["traveldistance"],
travelingDuration: json["travelingDuration"],
);
Map<String, dynamic> toJson() => {
"parkingAddress": parkingAddress,
"tracks": List<dynamic>.from(tracks.map((x) => x)),
"traveldistance": traveldistance,
"travelingDuration": travelingDuration,
};
}
class Driver {
Driver({
required this.name,
required this.phone,
});
String name;
String phone;
factory Driver.fromJson(Map<String, dynamic> json) => Driver(
name: json["name"],
phone: json["phone"],
);
Map<String, dynamic> toJson() => {
"name": name,
"phone": phone,
};
}
class Position {
Position({
required this.fixTime,
required this.speed,
required this.bearing,
required this.address,
required this.latlng,
required this.attributes,
});
DateTime fixTime;
int speed;
int bearing;
String address;
List<double> latlng;
Attributes attributes;
factory Position.fromJson(Map<String, dynamic> json) => Position(
fixTime: DateTime.parse(json["fixTime"]),
speed: json["speed"],
bearing: json["bearing"],
address: json["address"],
latlng: List<double>.from(json["latlng"].map((x) => x.toDouble())),
attributes: Attributes.fromJson(json["attributes"]),
);
Map<String, dynamic> toJson() => {
"fixTime": fixTime.toIso8601String(),
"speed": speed,
"bearing": bearing,
"address": address,
"latlng": List<dynamic>.from(latlng.map((x) => x)),
"attributes": attributes.toJson(),
};
}
class Attributes {
Attributes({
this.alarm,
this.immobile,
required this.odometer,
required this.fuelUsed,
required this.avgFuelUsed,
required this.ignition,
required this.coolantTemp,
required this.power,
required this.battery,
});
dynamic alarm;
dynamic immobile;
int odometer;
double fuelUsed;
double avgFuelUsed;
bool ignition;
int coolantTemp;
double power;
double battery;
factory Attributes.fromJson(Map<String, dynamic> json) => Attributes(
alarm: json["alarm"],
immobile: json["immobile"],
odometer: json["odometer"],
fuelUsed: json["fuelUsed"].toDouble(),
avgFuelUsed: json["avgFuelUsed"].toDouble(),
ignition: json["ignition"],
coolantTemp: json["coolantTemp"],
power: json["power"].toDouble(),
battery: json["battery"].toDouble(),
);
Map<String, dynamic> toJson() => {
"alarm": alarm,
"immobile": immobile,
"odometer": odometer,
"fuelUsed": fuelUsed,
"avgFuelUsed": avgFuelUsed,
"ignition": ignition,
"coolantTemp": coolantTemp,
"power": power,
"battery": battery,
};
}
this is how i use the fetched data
import 'dart:async';
import 'dart:convert';
import 'package:changenotifier/car_screen.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:changenotifier/models/members.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<List<Vehicle>> futureVehicle;
@override
void initState() {
super.initState();
futureVehicle = fetchVehicle();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primaryColor: Colors.grey.shade100,
),
home: Scaffold(
appBar: AppBar(
title: Text('Fetch Data Example'),
),
body: FutureBuilder<List<Vehicle>>(
future: futureVehicle,
builder: (context, snapshot) {
if (snapshot.hasData) {
return (ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (_, index) => GestureDetector(
onTap: () => Navigator.of(context).push(
MaterialPageRoute(
fullscreenDialog: true,
// ignore: prefer_const_constructors
builder: (context) => carscreen(snapshot.data![index]),
),
),
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
padding: EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(15.0),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${snapshot.data![index].name}",
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 10),
Text("${snapshot.data![index].id}"),
SizedBox(height: 10),
Text("${snapshot.data![index].status}"),
SizedBox(height: 10),
Text("${snapshot.data![index].vehicleId}"),
SizedBox(height: 10),
Text("${snapshot.data![index].motionState}"),
],
),
),
),
));
} else {
return Center(child: CircularProgressIndicator());
}
},
),
),
);
}
}
CodePudding user response:
You have to check for the null
before parsing it to your model class using a map
.
for example:
position: json["position"] == null ? null : Position.fromJson(json["position"]),
Here position
in your JSON response is null and it will fail during parsing.
Also, https://app.quicktype.io/ should've generated a model class with these null checks.
EDIT
Adding full generated model class.
// To parse this JSON data, do
//
// final welcome = welcomeFromJson(jsonString);
import 'dart:convert';
List<Welcome> welcomeFromJson(String str) => List<Welcome>.from(json.decode(str).map((x) => Welcome.fromJson(x)));
String welcomeToJson(List<Welcome> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Welcome {
Welcome({
this.id,
this.name,
this.status,
this.position,
this.vehicleId,
this.driver,
this.motionState,
this.motionTime,
this.immobileFeature,
this.geofenceIds,
this.deviceState,
});
int id;
String name;
String status;
Position position;
int vehicleId;
Driver driver;
String motionState;
DateTime motionTime;
bool immobileFeature;
List<dynamic> geofenceIds;
DeviceState deviceState;
factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
id: json["id"],
name: json["name"],
status: json["status"],
position: json["position"] == null ? null : Position.fromJson(json["position"]),
vehicleId: json["vehicleId"],
driver: json["driver"] == null ? null : Driver.fromJson(json["driver"]),
motionState: json["motionState"],
motionTime: json["motionTime"] == null ? null : DateTime.parse(json["motionTime"]),
immobileFeature: json["immobileFeature"],
geofenceIds: json["geofenceIds"] == null ? null : List<dynamic>.from(json["geofenceIds"].map((x) => x)),
deviceState: json["deviceState"] == null ? null : DeviceState.fromJson(json["deviceState"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"status": status,
"position": position == null ? null : position.toJson(),
"vehicleId": vehicleId,
"driver": driver == null ? null : driver.toJson(),
"motionState": motionState,
"motionTime": motionTime == null ? null : motionTime.toIso8601String(),
"immobileFeature": immobileFeature,
"geofenceIds": geofenceIds == null ? null : List<dynamic>.from(geofenceIds.map((x) => x)),
"deviceState": deviceState == null ? null : deviceState.toJson(),
};
}
class DeviceState {
DeviceState({
this.parkingAddress,
this.tracks,
this.traveldistance,
this.travelingDuration,
});
String parkingAddress;
List<dynamic> tracks;
int traveldistance;
int travelingDuration;
factory DeviceState.fromJson(Map<String, dynamic> json) => DeviceState(
parkingAddress: json["parkingAddress"],
tracks: List<dynamic>.from(json["tracks"].map((x) => x)),
traveldistance: json["traveldistance"],
travelingDuration: json["travelingDuration"],
);
Map<String, dynamic> toJson() => {
"parkingAddress": parkingAddress,
"tracks": List<dynamic>.from(tracks.map((x) => x)),
"traveldistance": traveldistance,
"travelingDuration": travelingDuration,
};
}
class Driver {
Driver({
this.name,
this.phone,
});
String name;
String phone;
factory Driver.fromJson(Map<String, dynamic> json) => Driver(
name: json["name"],
phone: json["phone"],
);
Map<String, dynamic> toJson() => {
"name": name,
"phone": phone,
};
}
class Position {
Position({
this.fixTime,
this.speed,
this.bearing,
this.address,
this.latlng,
this.attributes,
});
DateTime fixTime;
int speed;
int bearing;
String address;
List<double> latlng;
Attributes attributes;
factory Position.fromJson(Map<String, dynamic> json) => Position(
fixTime: DateTime.parse(json["fixTime"]),
speed: json["speed"],
bearing: json["bearing"],
address: json["address"],
latlng: List<double>.from(json["latlng"].map((x) => x.toDouble())),
attributes: Attributes.fromJson(json["attributes"]),
);
Map<String, dynamic> toJson() => {
"fixTime": fixTime.toIso8601String(),
"speed": speed,
"bearing": bearing,
"address": address,
"latlng": List<dynamic>.from(latlng.map((x) => x)),
"attributes": attributes.toJson(),
};
}
class Attributes {
Attributes({
this.alarm,
this.immobile,
this.odometer,
this.fuelUsed,
this.avgFuelUsed,
this.ignition,
this.coolantTemp,
this.power,
this.battery,
});
dynamic alarm;
dynamic immobile;
int odometer;
double fuelUsed;
double avgFuelUsed;
bool ignition;
int coolantTemp;
double power;
double battery;
factory Attributes.fromJson(Map<String, dynamic> json) => Attributes(
alarm: json["alarm"],
immobile: json["immobile"],
odometer: json["odometer"],
fuelUsed: json["fuelUsed"].toDouble(),
avgFuelUsed: json["avgFuelUsed"].toDouble(),
ignition: json["ignition"],
coolantTemp: json["coolantTemp"],
power: json["power"].toDouble(),
battery: json["battery"].toDouble(),
);
Map<String, dynamic> toJson() => {
"alarm": alarm,
"immobile": immobile,
"odometer": odometer,
"fuelUsed": fuelUsed,
"avgFuelUsed": avgFuelUsed,
"ignition": ignition,
"coolantTemp": coolantTemp,
"power": power,
"battery": battery,
};
}
CodePudding user response:
Only you need change model and Api
I am already call this type API you go to my git hub link and understand concept.
API link: https://jsonplaceholder.typicode.com/posts
GitHub link: https://github.com/JayswalViraj/API_With_Model/blob/main/lib/API Helper ( Methods )/api_home.dart