json - 未处理的异常:NoSuchMethodError:尝试从 API 检索数据时,在 null 上调用了方法“map”
问题描述
我正在尝试从我的项目中的 API 获取 JSON 数据。但是,我遇到了一个错误,我完全被卡住了。在反序列化 JSON 对象方面,我相当陌生,因此感谢您对此的帮助。
这是我的 JSON 文件
{
"status": 200,
"data": [
{
"id": 1,
"title": "Down-sized 4thgeneration leverage",
"description": "Distinctio voluptas ea aliquid",
"address": "2755 Raul Estate\nWest Ervin, AZ 14265-2763",
"postcode": "42503-7193",
"phoneNumber": "387-842-0455x71431",
"latitude": "-60.964344",
"longitude": "-12.024244",
"image": {
"small": "http://lorempixel.com/200/200/cats/1/",
"medium": "http://lorempixel.com/400/400/cats/1/",
"large": "http://lorempixel.com/800/800/cats/1/"
}
},
{
"id": 2,
"title": "Optional intermediate orchestration",
"description": "Quia unde officiis ut eum",
"postcode": "06445-4404",
"phoneNumber": "103-350-9440x83127",
"latitude": "-84.165738",
"longitude": "62.221246",
"image": {
"small": "http://lorempixel.com/200/200/cats/2/",
"medium": "http://lorempixel.com/400/400/cats/2/",
"large": "http://lorempixel.com/800/800/cats/2/"
}
}
]
}
我的主文件部分如下:
body: Container(
child: Column(
children: [
///////// Future Builder checks the API service getusers() future method every refreshed time
Expanded(child: FutureBuilder(
future: apiService.getCars(),
builder: (context , snapshot){
if(snapshot.hasData)
{
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index){
////// User List item button
return GestureDetector(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CarDetails(
car: snapshot.data[index].data[index].title,
)),
);
},
child:
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow( color: Colors.grey.withOpacity(0.3),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 5),
)
],
),
margin: EdgeInsets.symmetric(horizontal: 10 , vertical: 10),
padding: EdgeInsets.symmetric(horizontal: 10 , vertical: 10),
child: ListTile(
title: Text( snapshot.data[index].datalist[index].title , style: TextStyle(
fontSize: 18,color: Colors.black
),),
subtitle: Text( 'car Name', style: TextStyle(
fontSize: 18,color: Colors.black
),),
),
),
);
});
}else{
//////// Loading Circle from Spinkit Plugin
return Container(
child: Center(
child: SpinKitCircle(
color: Colors.orange,
),
),
);
}
},
))
],
) ,
),
这是我的豆类(car.dart)
import 'dart:convert';
Car carFromJson(String str) => Car.fromJson(json.decode(str));
String carToJson(Car data) => json.encode(data.toJson());
class Car {
Car({
this.status,
this.data,
});
int status;
List<Datum> data;
factory Car.fromJson(Map<String, dynamic> json) => Car(
status: json["status"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
Datum({
this.id,
this.title,
this.description,
this.address,
this.postcode,
this.phoneNumber,
this.latitude,
this.longitude,
this.image,
});
int id;
String title;
String description;
String address;
String postcode;
String phoneNumber;
String latitude;
String longitude;
Image image;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
title: json["title"],
description: json["description"],
address: json["address"],
postcode: json["postcode"],
phoneNumber: json["phoneNumber"],
latitude: json["latitude"],
longitude: json["longitude"],
image: Image.fromJson(json["image"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"title": title,
"description": description,
"address": address,
"postcode": postcode,
"phoneNumber": phoneNumber,
"latitude": latitude,
"longitude": longitude,
"image": image.toJson(),
};
}
class Image {
Image({
this.small,
this.medium,
this.large,
});
String small;
String medium;
String large;
factory Image.fromJson(Map<String, dynamic> json) => Image(
small: json["small"],
medium: json["medium"],
large: json["large"],
);
Map<String, dynamic> toJson() => {
"small": small,
"medium": medium,
"large": large,
};
}
这是我的 get cars 方法和 JSON 响应正文
Future<List<Car>> getCars() async {
final response = await http.get(Uri.parse(apiUrl));
///// checking the status code is successful
if (response.statusCode == 200) {
return getCarList(response.body);
} else {
throw Exception('Unable to fetch data from API');
}
}
List<Car> getCarList(String responseBody) {
final parsed = json.decode(responseBody);
final List<dynamic> cars= parsed["data"];
return (cars.map((json) => Car.fromJson(json)).toList());
}
我收到此错误:“未处理的异常:NoSuchMethodError:在 null 上调用了方法 'map'。”
这是我的调试控制台所说的:
E/flutter ( 6246): [ERROR:flutter/lib/ui/ui_dart_state.cc(213)] Unhandled Exception: NoSuchMethodError: The method 'map' was called on null.
E/flutter ( 6246): Receiver: null
E/flutter ( 6246): Tried calling: map(Closure: (dynamic) => Datum)
E/flutter ( 6246): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:63:5)
E/flutter ( 6246): #1 new Car.fromJson (package:flutter_car_booking/car.dart:61:41)
E/flutter ( 6246): #2 RestAPIService.getCarList.<anonymous closure> (package:flutter_car_booking/api_service.dart:54:39)
E/flutter ( 6246): #3 MappedListIterable.elementAt (dart:_internal/iterable.dart:413:31)
E/flutter ( 6246): #4 ListIterator.moveNext (dart:_internal/iterable.dart:342:26)
E/flutter ( 6246): #5 new _GrowableList._ofEfficientLengthIterable (dart:core-patch/growable_array.dart:188:27)
E/flutter ( 6246): #6 new _GrowableList.of (dart:core-patch/growable_array.dart:150:28)
E/flutter ( 6246): #7 new List.of (dart:core-patch/array_patch.dart:50:28)
E/flutter ( 6246): #8 ListIterable.toList (dart:_internal/iterable.dart:213:44)
E/flutter ( 6246): #9 RestAPIService.getCarList (package:flutter_car_booking/api_service.dart:54:55)
E/flutter ( 6246): #10 RestAPIService.getCars (package:flutter_car_booking/api_service.dart:23:10)
E/flutter ( 6246): <asynchronous suspension>
解决方案
问题是您将 respons.body["data"]["data"] 传递给 Datum.fromJson() 构造函数,但 json 中没有这样的键。另一方面,您将 response.body["data"] 传递给 Car.fromJson() 构造函数,这是一个没有“status”键的数据列表。
尝试如下更改您的代码。
Future<Car> getCars() async {
final response = await http.get(Uri.parse(apiUrl));
///// checking the status code is successful
if (response.statusCode == 200) {
return getCarList(response.body);
} else {
throw Exception('Unable to fetch data from API');
}
}
Car getCarList(String responseBody) {
final Map<String, dynamic> cars= json.decode(responseBody);
return (Car.fromJson(cars));
}
而你的 Car 类如下。
class Car {
Car({
this.status,
this.data,
});
int status;
List<Datum> data;
factory Car.fromJson(Map<String, dynamic> json) => Car(
status: json["status"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
改变你的build
方法如下。因为现在你没有一个列表,snapshot
它是一个Car
对象,它具有包含对象data
列表的属性Datum
body: Container(
child: Column(
children: [
///////// Future Builder checks the API service getusers() future method every refreshed time
Expanded(child: FutureBuilder<Car>(
future: apiService.getCars(),
builder: (BuildContext context ,AsyncSnapshot<Car> snapshot){
if(snapshot.hasData)
{
return ListView.builder(
itemCount: snapshot.data.data.length,
itemBuilder: (context, index){
////// User List item button
return GestureDetector(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CarDetails(
car: snapshot.data.data[index].title,
)),
);
},
child:
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow( color: Colors.grey.withOpacity(0.3),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 5),
)
],
),
margin: EdgeInsets.symmetric(horizontal: 10 , vertical: 10),
padding: EdgeInsets.symmetric(horizontal: 10 , vertical: 10),
child: ListTile(
title: Text( snapshot.data.data[index].title , style: TextStyle(
fontSize: 18,color: Colors.black
),),
subtitle: Text( 'car Name', style: TextStyle(
fontSize: 18,color: Colors.black
),),
),
),
);
});
}else{
//////// Loading Circle from Spinkit Plugin
return Container(
child: Center(
child: SpinKitCircle(
color: Colors.orange,
),
),
);
}
},
))
],
) ,
),
推荐阅读
- javascript - CSS 媒体查询在 Microsoft Edge 上不起作用
- r - 从列表中的行匹配的数据框中删除行
- javascript - Chrome 调试器 - 显示重复路径的“无域”部分(在 Webpack 之后)
- c# - 如何在 Xamarin 表单中创建动态单选按钮组?
- php - 使用 DOMDocument 以缩小形式保存 XML 文件
- php - 如何在 laravel 5.6 刀片中获取计数值?
- ios - Swift 4.2 - 如何在枚举函数中使用警报?
- angularjs - 执行 CORS 时自定义标头不可用
- android - Recyclerview滚动缓慢并卡住android
- ios - 在我的应用程序中点击 UITextField 时没有出现 UIKeyboard