Flutter中如何通过POST方法发送多类型必填参数数据
Flutter POST API 多类型参数提交失败问题
问题描述
在Flutter中调用POST API提交数据时遇到问题,需发送包含list、string、int、datetime等多种数据类型的必填参数(服务器要求所有字段不可为null)。仅发送字符串参数时能正常运行,但多类型参数提交时出现错误,至今未找到解决办法。
错误截图
请求失败截图:
API文档截图:
相关代码
sendBiodata 方法代码
Future<UserBiodata> sendBiodata( String? stAgama, // List<Agama>? agama, String? stKwn, // List<Kwn>? kwn, String? tempat, String? tglLahir, String? nik, String? nisn, String? npwp, String? jalan, String? stProv, // List<Province>? province, String? stKab, // List<Province>? kab, String? stKec, // List<Province>? kec, String? desa, String? dusun, String? rt, String? rw, String? kodePos, dynamic telp, String? email, String kps, String? stTrans, // List<Trans>? trans, String? stJn, // List<Jn>? jn, String? ipk, // int? smt, String? namaAyah, String? nikAyah, String? tglLahirAyah, String? stPendidikanAyah, // List<PendidikanAyah>? pendidikanAyah, String? pekerjaanAyah, String? penghasilanAyah, String? namaIbu, String? nikIbu, String? tglLahirIbu, String? stPendidikanIbu, // List<PendidikanIbu>? pendidikanIbu, String? pekerjaanIbu, String? penghasilanIbu, String? namaWali, String? nikWali, String? tglLahirWali, String? stPendidikanWali, // List<PendidikanWali>? pendidikanWali, String? pekerjaanWali, String? penghasilanWali, ) async { String url = Constant.baseURL; String token = await UtilSharedPreferences.getToken(); final response = await http.post( Uri.parse( '$url/auth/mhs_siakad/biodata/update', ), headers: <String, String>{ 'Authorization': 'Bearer $token', 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode<String, dynamic>({ "st_agama": stAgama, // 'agama': agama, 'st_kwn': stKwn, // 'kwn': kwn, "tempat": tempat, "tgl_lahir": tglLahir, "nik": nik, "nisn": nisn, "npwp": npwp, "jalan": jalan, "st_prov": stProv, // 'province': province, "st_kab": stKab, // 'kab': kab, "st_kec": stKec, // 'kec': kec, "desa": desa, "dusun": dusun, "rt": rt, "rw": rw, "kode_pos": kodePos, "telp": telp, "email": email, "kps": kps, "st_trans": stTrans, // 'trans': trans, "st_jn": stJn, // "jn": jn, "ipk": ipk, // "smt": smt, "nama_ayah": namaAyah, "nik_ayah": nikAyah, "tgl_lahir_ayah": tglLahirAyah, "st_pendidikan_ayah": stPendidikanAyah, // "pendidikan_ayah": pendidikanAyah, "pekerjaan_ayah": pekerjaanAyah, "penghasilan_ayah": penghasilanAyah, "nama_ibu": namaIbu, "nik_ibu": nikIbu, "tgl_lahir_ibu": tglLahirIbu, "st_pendidikan_ibu": stPendidikanIbu, // "pendidikan_ibu": pendidikanIbu, "pekerjaan_ibu": pekerjaanIbu, "penghasilan_ibu": penghasilanIbu, "nama_wali": namaWali, "nik_wali": nikWali, "tgl_lahir_wali": tglLahirWali, "st_pendidikan_wali": stPendidikanWali, // "pendidikan_wali": pendidikanWali, "pekerjaan_wali": pekerjaanWali, "penghasilan_wali": penghasilanWali, }), ); print(response.statusCode); print(response.body); if (response.statusCode == 201) { return UserBiodata.fromJson(jsonDecode(response.body)); } else { throw Exception('Failed update data!'); } }
提交按钮代码
Center( child: ElevatedButton( onPressed: () { setState(() { _futureBiodata = BiodataProvider().sendBiodata( _controllerAgama.text, // _controller2.text as List<Agama>?, _controllerKwn.text, // _controller4.text as List<Kwn>?, _controllerTmtLahir.text, _controllerTglLahir.text, _controllerNik.text, _controllerNisn.text, _controllerNpwp.text, _controllerAlamat.text, _controllerProv.text, // _controller12.text as List<Province>?, _controllerKab.text, // _controller14.text as List<Province>?, _controllerKec.text, // _controller16.text as List<Province>?, _controllerKel.text, _controllerDusun.text, _controllerRt.text, _controllerRw.text, _controllerKdPos.text, _controllerNoHp.text, _controllerEmail.text, _controllerKps.text, _controllerNoKps.text, // _controller26.text as List<Trans>?, _controllerTrans.text, // _controller28.text as List<Jn>?, _controllerJnsTinggal.text, // _controller30.text as int?, _controllerNmAyah.text, _controllerNikAyah.text, _controllerTglLhrAyah.text, _controllerPendidikanAyah.text, // _controller35.text as List<PendidikanAyah>?, _controllerPekerjaanAyah.text, _controllerPenghasilanAyah.text, _controllerNmIbu.text, _controllerNikIbu.text, _controllerTglLhrIbu.text, _controllerPekerjaanIbu.text, // _controller42.text as List<PendidikanIbu>?, _controllerPekerjaanIbu.text, _controllerPenghasilanIbu.text, _controllerNmWali.text, _controllerNikWali.text, _controllerTglLhrWali.text, _controllerPendidikanWali.text, // _controller49.text as List<PendidikanWali>?, _controllerPekerjaanWali.text, _controllerPekerjaanWali.text, ); }); }, child: const Text('Update Data'), ), ),
解决方案
1. 强制参数非空
服务器要求所有字段不可为null,当前代码中大部分参数为String?类型,存在提交null值的风险:
- 将必填参数的类型从
String?改为String,强制调用方传入非空值 - 提交前对所有文本控制器做非空校验,比如
if(_controllerAgama.text.isEmpty) return;,避免空字符串提交
2. 修正数据类型匹配
- telp字段:若服务器要求int类型,需将控制器的字符串转换为整数:
int.parse(_controllerNoHp.text),注意捕获转换异常 - ipk字段:若服务器要求数字类型(float/double),执行
double.parse(_controllerIpk.text)转换 - 日期字段:确保
tgl_lahir等字段格式与服务器要求一致(如yyyy-MM-dd),若控制器格式不符,先通过DateFormat类转换
3. 修复按钮参数顺序错误
查看按钮调用sendBiodata的代码,存在参数重复传入的问题:
_controllerPekerjaanIbu.text, // _controller42.text as List<PendidikanIbu>?, _controllerPekerjaanIbu.text, // 此处应为_controllerPendidikanIbu.text
参数顺序必须与方法定义完全一致,否则会导致字段值错位,触发服务器校验失败
4. 处理List类型参数
若需要提交注释掉的List参数(如agama、province):
- 确认服务器期望的List结构:是ID数组还是对象数组
- 若为ID数组,拆分控制器文本并转换:
_controllerAgama.text.split(',').map(int.parse).toList() - 若为对象数组,将选中的选项转换为对应实体类的JSON格式后传入
5. 调试优化
在jsonEncode前打印请求体,检查是否存在null值或类型不匹配:
final requestBody = { // 所有字段 }; print('Request Body: $requestBody'); body: jsonEncode(requestBody),
查看response.body的具体错误信息,服务器通常会返回字段校验失败的详情,根据提示针对性修正
内容的提问来源于stack exchange,提问作者Meikisihka
相关产品推荐
相关产品推荐

