简体   繁体   中英

Flutter: Unhandled Exception: Converting object to an encodable object failed: Instance of 'AddProjectModel'

each time I try to send data to API I got the following error:

" Unhandled Exception: Converting object to an encodable object failed: Instance of 'AddProjectModel' ".

I followed the debugger step by step everything went well, and all data are passed correctly. However, when it reaches the jsonEncode() method it gives the above error.

Anyone can help please, thanks in advance.

Here is my AddProjectModel and other models used inside it:

class AddProjectModel {
  AddProjectModel({
    required this.name,
    required this.city,
    required this.district,
    required this.address,
    required this.size,
    required this.completionDate,
    required this.infrastructureCost,
    required this.currencyID,
    required this.description,
    required this.isHidden,
    required this.companies,
    required this.facilities,
    required this.picture,
  });
  late final String name;
  late final String city;
  late final String district;
  late final String address;
  late final double size;
  late final DateTime completionDate;
  late final double infrastructureCost;
  late final int currencyID;
  late final String description;
  late final bool isHidden;
  late final List<AddProjectCompaniesModel> companies;
  late final List<AddEditFacilitiesModel> facilities;
  late final List<AddProjectPicturesModel> picture;

  AddProjectModel.fromJson(Map<String, dynamic> json) {
    name = json['name'];
    city = json['city'];
    district = json['district'];
    address = json['address'];
    size = json['size'].toDouble();
    completionDate = json['completeDate'];
    infrastructureCost = json['infrastructureCost'].toDouble();
    currencyID = json['currencyID'];
    description = json['description'];
    isHidden = json['isHidden'];
    companies = List.from(json['companies'])
        .map((e) => AddProjectCompaniesModel.fromJson(e))
        .toList();
    facilities = List.from(json['facilities'])
        .map((e) => AddEditFacilitiesModel.fromJson(e))
        .toList();
    picture = List.from(json['picture'])
        .map((e) => AddProjectPicturesModel.fromJson(e))
        .toList();
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['name'] = name;
    data['city'] = city;
    data['district'] = district;
    data['address'] = address;
    data['size'] = size;
    data['completeDate'] = completionDate;
    data['infrastructureCost'] = infrastructureCost;
    data['currencyID'] = currencyID;
    data['description'] = description;
    data['isHidden'] = isHidden;
    data['companies'] = companies.map((e) => e.toJson()).toList();
    data['facilities'] = facilities.map((e) => e.toJson()).toList();
    data['picture'] = picture.map((e) => e.toJson()).toList();
    return data;
  }
}

class AddProjectCompaniesModel {
  AddProjectCompaniesModel({
    required this.companyId,
  });
  late final int companyId;

  AddProjectCompaniesModel.fromJson(Map<String, dynamic> json) {
    companyId = json['companyId'];
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['companyId'] = companyId;
    return data;
  }
}

class AddEditFacilitiesModel {
  AddEditFacilitiesModel({
    required this.pool,
    required this.gym,
    required this.garage,
    required this.garden,
    required this.roofRoom,
    required this.barbecuePlace,
    required this.cafeterias,
    required this.giftShop,
    required this.gamingCenter,
    required this.supermarket,
    required this.atm,
    required this.playGround,
    required this.parking,
    required this.walkingArea,
    required this.pharmacy,
    required this.dryCleaning,
    required this.spaCenter,
    required this.medicalServices,
  });

  late final bool pool;
  late final bool gym;
  late final bool garage;
  late final bool garden;
  late final bool roofRoom;
  late final bool barbecuePlace;
  late final bool cafeterias;
  late final bool giftShop;
  late final bool gamingCenter;
  late final bool supermarket;
  late final bool atm;
  late final bool playGround;
  late final bool parking;
  late final bool walkingArea;
  late final bool pharmacy;
  late final bool dryCleaning;
  late final bool spaCenter;
  late final bool medicalServices;

  AddEditFacilitiesModel.fromJson(Map<String, dynamic> json) {
    pool = json['pool'];
    gym = json['gym'];
    garage = json['garage'];
    garden = json['garden'];
    roofRoom = json['roofRoom'];
    barbecuePlace = json['barbecuePlace'];
    cafeterias = json['cafeterias'];
    giftShop = json['giftShop'];
    gamingCenter = json['gamingCenter'];
    supermarket = json['superMarket'];
    atm = json['atm'];
    playGround = json['playGround'];
    parking = json['parking'];
    walkingArea = json['walkingArea'];
    pharmacy = json['pharmacy'];
    dryCleaning = json['drycleaning'];
    spaCenter = json['spacenter'];
    medicalServices = json['medicalservices'];
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['pool'] = pool;
    data['gym'] = gym;
    data['garage'] = garage;
    data['garden'] = garden;
    data['roofRoom'] = roofRoom;
    data['barbecuePlace'] = barbecuePlace;
    data['cafeterias'] = cafeterias;
    data['giftShop'] = giftShop;
    data['gamingCenter'] = gamingCenter;
    data['superMarket'] = supermarket;
    data['atm'] = atm;
    data['playGround'] = playGround;
    data['parking'] = parking;
    data['walkingArea'] = walkingArea;
    data['pharmacy'] = pharmacy;
    data['drycleaning'] = dryCleaning;
    data['spacenter'] = spaCenter;
    data['medicalservices'] = medicalServices;
    return data;
  }
}

class AddProjectPicturesModel {
  AddProjectPicturesModel({
    this.url,
    required this.file,
    this.dateAdded,
  });
  late String? url;
  late final String file;
  late String? dateAdded;

  AddProjectPicturesModel.fromJson(Map<String, dynamic> json) {
    url = json['url'];
    file = json['file'];
    dateAdded = json['dateAdded'];
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['url'] = url;
    data['file'] = file;
    data['dateAdded'] = dateAdded;
    return data;
  }
}

Here is my addProject() method that posts data to API:

static Future<bool> addProject(
    String name,
    String city,
    String district,
    String address,
    double size,
    DateTime completionDate,
    double infrastructureCost,
    int currencyID,
    String description,
    bool isHidden,
    List<AddProjectCompaniesModel> companies,
    List<AddEditFacilitiesModel> facilities,
    List<AddProjectPicturesModel> projectPicture,
  ) async {
    AddProjectModel projectModel = AddProjectModel(
      name: name,
      city: city,
      district: district,
      address: address,
      size: size,
      completionDate: completionDate,
      infrastructureCost: infrastructureCost,
      currencyID: currencyID,
      description: description,
      isHidden: isHidden,
      companies: companies,
      facilities: facilities,
      picture: projectPicture,
    );

    final url = Uri.https(APIRoutes.baseURL, APIRoutes.project);

    Map<String, String> requestHeaders = {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ${secureStorage.token}',
    };

    final response = await client.post(
      url,
      headers: requestHeaders,
      body: jsonEncode(projectModel),
    );

    if (response.statusCode == 201) {
      print('Success with: ${response.statusCode}');
      return true;
    } else {
      print('Failed with: ${response.statusCode}');
      return false;
    }
  }

那是因为 dart 对象默认是不能转换成 json 的,你需要先把它转换成Map或者你可以使用插件把你的对象转换成json_serializable 之类的映射

The problem was a failer in converting an Object to an encodable Object through the jsonEncode() method "which is supported in dart:convert library".

Here is Flutter explanation for jsonEncode() method

As shown in the figure above, we are only allowed to convert values of type "number, boolean, string, null, list, or a map with string keys". So, the issue in my question was not in the following objects:

    List<AddProjectCompaniesModel> companies
    List<AddEditFacilitiesModel> facilities
    List<AddProjectPicturesModel> projectPicture

because these are of type List and no issues with them. However, the issue was in the following lines of code

    DateTime completionDate, // inside addProject(...)
    late final DateTime completionDate; // inside AddProjectModel{}
    data['completeDate'] = completionDate; // inside toJson() of AddProjectModel{}

Where I am was trying to convert a value of type DateTime and it is not allowed as shown in method explanation in the figure above. Beacuse of that I had to convert the completionDate variable from 'DateTime' to 'String' before converting it to json format. And after that it works fine.

Therfore, the solution is to change this line of code

    data['completeDate'] = completionDate; // inside toJson() of AddProjectModel{}

To

    data['completeDate'] = completionDate.toString();

I hope my answer was explained enough. Below you can view the whole corrected code.

AddProjectModel and other models used inside it:

class AddProjectModel {
  AddProjectModel({
    required this.name,
    required this.city,
    required this.district,
    required this.address,
    required this.size,
    required this.completionDate,
    required this.infrastructureCost,
    required this.currencyID,
    required this.description,
    required this.isHidden,
    required this.companies,
    required this.facilities,
    required this.picture,
  });
  late final String name;
  late final String city;
  late final String district;
  late final String address;
  late final double size;
  late final DateTime completionDate;
  late final double infrastructureCost;
  late final int currencyID;
  late final String description;
  late final bool isHidden;
  late final List<AddProjectCompaniesModel> companies;
  late final List<AddEditFacilitiesModel> facilities;
  late final List<AddProjectPicturesModel> picture;

  AddProjectModel.fromJson(Map<String, dynamic> json) {
    name = json['name'];
    city = json['city'];
    district = json['district'];
    address = json['address'];
    size = json['size'].toDouble();
    completionDate = json['completeDate'];
    infrastructureCost = json['infrastructureCost'].toDouble();
    currencyID = json['currencyID'];
    description = json['description'];
    isHidden = json['isHidden'];
    companies = List.from(json['companies'])
        .map((e) => AddProjectCompaniesModel.fromJson(e))
        .toList();
    facilities = List.from(json['facilities'])
        .map((e) => AddEditFacilitiesModel.fromJson(e))
        .toList();
    picture = List.from(json['picture'])
        .map((e) => AddProjectPicturesModel.fromJson(e))
        .toList();
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['name'] = name;
    data['city'] = city;
    data['district'] = district;
    data['address'] = address;
    data['size'] = size;
    data['completeDate'] = completionDate.toSting(); //Only this line changed
    data['infrastructureCost'] = infrastructureCost;
    data['currencyID'] = currencyID;
    data['description'] = description;
    data['isHidden'] = isHidden;
    data['companies'] = companies.map((e) => e.toJson()).toList();
    data['facilities'] = facilities.map((e) => e.toJson()).toList();
    data['picture'] = picture.map((e) => e.toJson()).toList();
    return data;
  }
}

class AddProjectCompaniesModel {
  AddProjectCompaniesModel({
    required this.companyId,
  });
  late final int companyId;

  AddProjectCompaniesModel.fromJson(Map<String, dynamic> json) {
    companyId = json['companyId'];
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['companyId'] = companyId;
    return data;
  }
}

class AddEditFacilitiesModel {
  AddEditFacilitiesModel({
    required this.pool,
    required this.gym,
    required this.garage,
    required this.garden,
    required this.roofRoom,
    required this.barbecuePlace,
    required this.cafeterias,
    required this.giftShop,
    required this.gamingCenter,
    required this.supermarket,
    required this.atm,
    required this.playGround,
    required this.parking,
    required this.walkingArea,
    required this.pharmacy,
    required this.dryCleaning,
    required this.spaCenter,
    required this.medicalServices,
  });

  late final bool pool;
  late final bool gym;
  late final bool garage;
  late final bool garden;
  late final bool roofRoom;
  late final bool barbecuePlace;
  late final bool cafeterias;
  late final bool giftShop;
  late final bool gamingCenter;
  late final bool supermarket;
  late final bool atm;
  late final bool playGround;
  late final bool parking;
  late final bool walkingArea;
  late final bool pharmacy;
  late final bool dryCleaning;
  late final bool spaCenter;
  late final bool medicalServices;

  AddEditFacilitiesModel.fromJson(Map<String, dynamic> json) {
    pool = json['pool'];
    gym = json['gym'];
    garage = json['garage'];
    garden = json['garden'];
    roofRoom = json['roofRoom'];
    barbecuePlace = json['barbecuePlace'];
    cafeterias = json['cafeterias'];
    giftShop = json['giftShop'];
    gamingCenter = json['gamingCenter'];
    supermarket = json['superMarket'];
    atm = json['atm'];
    playGround = json['playGround'];
    parking = json['parking'];
    walkingArea = json['walkingArea'];
    pharmacy = json['pharmacy'];
    dryCleaning = json['drycleaning'];
    spaCenter = json['spacenter'];
    medicalServices = json['medicalservices'];
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['pool'] = pool;
    data['gym'] = gym;
    data['garage'] = garage;
    data['garden'] = garden;
    data['roofRoom'] = roofRoom;
    data['barbecuePlace'] = barbecuePlace;
    data['cafeterias'] = cafeterias;
    data['giftShop'] = giftShop;
    data['gamingCenter'] = gamingCenter;
    data['superMarket'] = supermarket;
    data['atm'] = atm;
    data['playGround'] = playGround;
    data['parking'] = parking;
    data['walkingArea'] = walkingArea;
    data['pharmacy'] = pharmacy;
    data['drycleaning'] = dryCleaning;
    data['spacenter'] = spaCenter;
    data['medicalservices'] = medicalServices;
    return data;
  }
}

class AddProjectPicturesModel {
  AddProjectPicturesModel({
    this.url,
    required this.file,
    this.dateAdded,
  });
  late String? url;
  late final String file;
  late String? dateAdded;

  AddProjectPicturesModel.fromJson(Map<String, dynamic> json) {
    url = json['url'];
    file = json['file'];
    dateAdded = json['dateAdded'];
  }

  Map<String, dynamic> toJson() {
    final data = <String, dynamic>{};
    data['url'] = url;
    data['file'] = file;
    data['dateAdded'] = dateAdded;
    return data;
  }
}

addProject() method that posts data to API:

static Future<bool> addProject(
    String name,
    String city,
    String district,
    String address,
    double size,
    DateTime completionDate,
    double infrastructureCost,
    int currencyID,
    String description,
    bool isHidden,
    List<AddProjectCompaniesModel> companies,
    List<AddEditFacilitiesModel> facilities,
    List<AddProjectPicturesModel> projectPicture,
  ) async {
    AddProjectModel projectModel = AddProjectModel(
      name: name,
      city: city,
      district: district,
      address: address,
      size: size,
      completionDate: completionDate,
      infrastructureCost: infrastructureCost,
      currencyID: currencyID,
      description: description,
      isHidden: isHidden,
      companies: companies,
      facilities: facilities,
      picture: projectPicture,
    );

    final url = Uri.https(APIRoutes.baseURL, APIRoutes.project);

    Map<String, String> requestHeaders = {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ${secureStorage.token}',
    };

    final response = await client.post(
      url,
      headers: requestHeaders,
      body: jsonEncode(projectModel),
    );

    if (response.statusCode == 201) {
      print('Success with: ${response.statusCode}');
      return true;
    } else {
      print('Failed with: ${response.statusCode}');
      return false;
    }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM