Flutter中Dio POST请求传参失败返回400错误如何解决?
Flutter Dio POST请求后端收不到参数的问题排查与解决
在Flutter中使用Dio发送POST请求时,无论通过user.toJson()、jsonEncode(user.toJson())、FormData.fromMap()还是手动硬编码传递数据,后端均无法接收参数(返回400错误,参数显示为null),但本地打印数据可见有效值。用Postman测试接口正常,原生http请求使用相同toJson()方法也能正常工作。
相关代码
1. Dio请求函数
Future<User?> registerUser({required User user}) async { User? retrievedUser; try { Response response = await _dio.post( 'http://localhost/api/v1/index.php/registration', data: user.toJson(), // 返回400状态码,参数被判定为null // 尝试过的方式: // user.toJson() // jsonEncode(user.toJson()) // json.encode(user.toJson()) // FormData.fromMap(user.toJson()) // FormData.fromMap(json.encode(user.toJson())) // 手动硬编码如{'first_name': 'sample',...} ); print('User created: ${response.data}'); retrievedUser = User.fromJson(response.data); } catch (e) { print('Error creating user: $e'); } return retrievedUser; }
2. 请求调用代码
FilledButton( onPressed: () async { User userInfo = User( firstName: firstNameController.text, lastName: lastNameController.text, birthday: birthdayController.text, gender: genderController.text, mobile: mobileController.text, ); User? retrievedUser = await registerUser(user: userInfo); print(retrievedUser); }, child: const Text('Register'), ),
3. User模型(JsonSerializable)
import 'package:json_annotation/json_annotation.dart'; part 'user.g.dart'; @JsonSerializable() class User { String firstName; String lastName; String birthday; String gender; String mobile; User( {required this.firstName, required this.lastName, required this.birthday, required this.gender, required this.mobile}); factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); Map<String, dynamic> toJson() => _$UserToJson(this); } // GENERATED CODE - DO NOT MODIFY BY HAND part of 'user.dart'; // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** User _$UserFromJson(Map<String, dynamic> json) => User( firstName: json['first_name'] as String, lastName: json['last_name'] as String, birthday: json['birthday'] as String, gender: json['gender'] as String, mobile: json['mobile'] as String, ); Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{ 'first_name': instance.firstName, 'last_name': instance.lastName, 'birthday': instance.birthday, 'gender': instance.gender, 'mobile': instance.mobile, };
4. 后端PHP接口代码
$app->post('/registration', function () use ($app){ //Required Parameters verifyRequiredParams(array('first_name','last_name','birthday','gender','mobile')); //includes $database = new Database(); $conn = $database->getConnection(); // $db = new SaveInfo($conn); $response = array(); $first_name = $app->request->post('first_name'); $last_name = $app->request->post('last_name'); $birthday = $app->request->post('birthday'); $gender = $app->request->post('gender'); $mobile = $app->request->post('mobile'); $result = $db->savePersonalInfo($first_name,$last_name,$birthday,$gender,$mobile); if($result){ $response['error'] = false; $response['message'] = "Successfully Registered"; } else{ $response['error'] = true; $response['message'] = "Failed to register"; } echoResponse(200,$response); });
问题核心原因
后端PHP代码使用$app->request->post()方法获取参数,该方法仅能解析**表单格式(application/x-www-form-urlencoded)**的请求体。而Dio默认发送的是JSON格式(Content-Type: application/json)的请求体,后端未配置JSON请求体的解析逻辑,因此无法读取参数,返回400错误。
原生http请求正常是因为其默认发送表单格式数据,Postman测试正常是因为你选择了表单格式(form-data或x-www-form-urlencoded)提交参数。
解决方案
方案1:修改Dio请求,发送表单格式数据
使用FormData构造请求数据,Dio会自动设置正确的Content-Type:
Future<User?> registerUser({required User user}) async { User? retrievedUser; try { // 直接传入user.toJson()的Map,无需jsonEncode FormData formData = FormData.fromMap(user.toJson()); Response response = await _dio.post( 'http://localhost/api/v1/index.php/registration', data: formData, ); print('User created: ${response.data}'); retrievedUser = User.fromJson(response.data); } catch (e) { print('Error creating user: $e'); } return retrievedUser; }
方案2:修改后端PHP代码,支持JSON请求体
如果希望后端兼容JSON格式请求,可修改接口代码解析JSON请求体:
$app->post('/registration', function () use ($app){ // 解析JSON请求体 $requestBody = json_decode(file_get_contents('php://input'), true); // 验证参数(需修改verifyRequiredParams函数,支持传入自定义参数数组) verifyRequiredParams(array('first_name','last_name','birthday','gender','mobile'), $requestBody); $database = new Database(); $conn = $database->getConnection(); $db = new SaveInfo($conn); $response = array(); $first_name = $requestBody['first_name']; $last_name = $requestBody['last_name']; $birthday = $requestBody['birthday']; $gender = $requestBody['gender']; $mobile = $requestBody['mobile']; $result = $db->savePersonalInfo($first_name,$last_name,$birthday,$gender,$mobile); if($result){ $response['error'] = false; $response['message'] = "Successfully Registered"; } else{ $response['error'] = true; $response['message'] = "Failed to register"; } echoResponse(200,$response); });
验证建议
可添加Dio拦截器打印请求头和请求体,确认格式是否正确:
_dio.interceptors.add(InterceptorsWrapper( onRequest: (options, handler) { print('Request Header: ${options.headers}'); print('Request Data: ${options.data}'); return handler.next(options); }, ));
内容的提问来源于stack exchange,提问作者Richard Johnson
相关产品推荐
相关产品推荐

