I'm building an app to return JSON data from an API. The error occurs when parsing the data for RouteLine.
route_table.dart
class RouteTable {
int? deliveryPeriod = 0;
String? driverId = "";
String? processId = "";
String? routeId = "";
RouteLine? routeLines;
int? status = 0;
String? vanId = "";
factory RouteTable.fromJson(Map<String, dynamic> json) {
return RouteTable(
deliveryPeriod: json['deliveryPeriod'],
driverId: json['driverId'],
processId: json['processId'],
routeId: json['routeId'],
routeLines: json['routeLines'] == null
? null
: RouteLine.fromJson(jsonDecode(json['routeLines'])),
status: json['status'],
vanId: json['vanId']);
}
route_line.dart
class RouteLine {
String? city = "";
String? custAccount = "";
String? custName = "";
String? invoiceId = "";
DateTime? deliveryDate = initDateTime();
int? productType = 0;
String? routeId = "";
String? salesId = "";
double? volume = 0.0;
double? weight = 0.0;
factory RouteLine.fromJson(Map<String, dynamic> json) {
return new RouteLine(
city: json['city'] as String,
custAccount: json['custAccount'] as String,
custName: json['custName'] as String,
invoiceId: json['invoiceId'] as String,
deliveryDate: json['deliveryDate'] as DateTime,
productType: json['productType'] as int,
routeId: json['routeId'] as String,
salesId: json['salesId'] as String,
volume: json['volume'] as double,
weight: json['weight'] as double,
);
}
main.dart file where I'm trying to display the results.
import 'dart:io';
import 'package:flutter/material.dart';
import 'route_line.dart';
import 'route_table.dart';
import 'networking.dart';
void main() {
HttpOverrides.global = new MyHttpOverrides();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// to set the root of app.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'API Demo Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, this.title = ""}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late Future<RouteTable> futureRouteTable;
@override
void initState() {
super.initState();
futureRouteTable = fetchData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("Flutter - API Implementation"),
),
body: Center(
child: // build list view & manage states
FutureBuilder<RouteTable>(
future: futureRouteTable,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final RouteTable? posts = snapshot.data;
if (snapshot.data != null) {
return Text(snapshot.data!.routeId.toString());
}
return Text('No Data');
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
)),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {},
label: Icon(Icons.cancel),
backgroundColor: Colors.green,
),
);
}
Future<RouteTable> fetchData() async {
final response =
await http.get(Uri.parse('https://10.0.2.2:7038/api/route/1?siteId=1'));
try {
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return RouteTable.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load route');
}
} catch (e) {
print(e);
}
return new RouteTable(
deliveryPeriod: 0,
driverId: "",
processId: "",
routeId: "",
routeLines: new RouteLine(
city: "",
custAccount: "",
custName: "",
invoiceId: "",
deliveryDate: new DateTime(2022),
productType: 0,
routeId: "",
salesId: "",
volume: 0.0,
weight: 0.0),
status: 0,
vanId: "");
}
}
The JSON data being returned
{
"deliveryPeriod":1,
"driverId":"",
"processId":"PRO000492",
"routeId":"ROU001858",
"routeLines":[
{
"city":"Naxxar",
"custAccount":"CUST010922",
"custName":"",
"deliveryDate":"2021-12-06T12:00:00",
"invoiceId":"",
"productType":0,
"routeId":"ROU001858",
"salesId":"SO002579",
"volume":0.019448889,
"weight":15.225435
}
],
"status":30,
"vanId":"TFI 943"
}
I'm running into the following error when trying to parse RouteLine inside RouteTable.fromJson.
type 'List<dynamic>' is not a subtype of type 'String'
Tried without the jsonDecode and get a similar error.
type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
How do I turn it to a List? What am I missing?
CodePudding user response:
You can use QuickType to convert JSON into Dart Models. Here is your dart data model which I generated through it.
import 'dart:convert';
class RouteTable {
RouteTable({
this.deliveryPeriod,
this.driverId,
this.processId,
this.routeId,
this.routeLines,
this.status,
this.vanId,
});
int deliveryPeriod;
String driverId;
String processId;
String routeId;
List<RouteLine> routeLines;
int status;
String vanId;
factory RouteTable.fromJson(Map<String, dynamic> json) => RouteTable(
deliveryPeriod: json["deliveryPeriod"],
driverId: json["driverId"],
processId: json["processId"],
routeId: json["routeId"],
routeLines: List<RouteLine>.from(json["routeLines"].map((x) => RouteLine.fromJson(x))),
status: json["status"],
vanId: json["vanId"],
);
Map<String, dynamic> toJson() => {
"deliveryPeriod": deliveryPeriod,
"driverId": driverId,
"processId": processId,
"routeId": routeId,
"routeLines": List<dynamic>.from(routeLines.map((x) => x.toJson())),
"status": status,
"vanId": vanId,
};
}
class RouteLine {
RouteLine({
this.city,
this.custAccount,
this.custName,
this.deliveryDate,
this.invoiceId,
this.productType,
this.routeId,
this.salesId,
this.volume,
this.weight,
});
String city;
String custAccount;
String custName;
DateTime deliveryDate;
String invoiceId;
int productType;
String routeId;
String salesId;
double volume;
double weight;
factory RouteLine.fromJson(Map<String, dynamic> json) => RouteLine(
city: json["city"],
custAccount: json["custAccount"],
custName: json["custName"],
deliveryDate: DateTime.parse(json["deliveryDate"]),
invoiceId: json["invoiceId"],
productType: json["productType"],
routeId: json["routeId"],
salesId: json["salesId"],
volume: json["volume"].toDouble(),
weight: json["weight"].toDouble(),
);
Map<String, dynamic> toJson() => {
"city": city,
"custAccount": custAccount,
"custName": custName,
"deliveryDate": deliveryDate.toIso8601String(),
"invoiceId": invoiceId,
"productType": productType,
"routeId": routeId,
"salesId": salesId,
"volume": volume,
"weight": weight,
};
}