You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:42:48