首页 > 解决方案 > 未处理的异常: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>

标签: jsonflutter

解决方案


问题是您将 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,
                      ),
                    ),
                  );
                }
              },
            ))

          ],
        ) ,
      ),

推荐阅读