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

如何在Dart MultipartRequest中正确添加含空值的请求字段?

Flutter文件上传时如何正确传递含null的JSON字段给Go API

问题背景

原本通过普通HTTP POST请求向Go API发送数据时,能正常传递{"date_required": null}或{"date_required": "2023-11-12"}格式的内容。但切换到MultipartRequest上传文件时,由于request.fields是Map<String, String>类型,无法直接传入null,导致传递的值变成(2023-11-12)或(null),Go API解析失败,不符合预期格式。

现有代码及错误历程

1. 原始非文件上传的字段处理代码

if (dateRequired != null) {
  data['date_required'] = dateRequired?.formatDbDate();
} else {
  data['date_required'] = null;
}

2. 上传文件核心代码

Future<dynamic> uploadFile(
      BuildContext context, User user, String dateRequiredString) async {
    final navigator = Navigator.of(context);

    const storage = FlutterSecureStorage();

    String? token = await storage.read(key: 'jwt');

    Map<String, String> headers = {
      "Authorization": "Bearer $token",
    };

    final bytes = file?.bytes;

    if (file == null || bytes == null) return;

    final multipartFile =
        http.MultipartFile.fromBytes('file', bytes, filename: file?.name);

    final request = http.MultipartRequest('POST', Uri.parse(user.fileUrl));

    request.files.add(multipartFile);

    request.headers.addAll(headers);

    request.fields['date_required'] = dateRequiredString;
}

3. 第一次修改尝试及错误

尝试将Map<String, dynamic>转JSON后强转为Map<String, String>:

if (_formKey.currentState!.validate()) {
  if (_formKey
          .currentState
          ?.fields['date_required']
          ?.value !=
      null) {
    dateRequired = _formKey.currentState
        ?.fields['date_required']!.value;
  }

  Map<String, dynamic> data = {
    'date_required': dateRequired != null
        ? dateRequired!.formatDbDate()
        : null
  };

  print(data);

  Map<String, String> dateRequiredString =
      jsonEncode(data)
          as Map<String, String>;

  print(dateRequiredString);
}

控制台报错:

{date_required: null}
Error: Expected a value of type 'Map<String, String>', but got one of type 'String'

4. 第二次修改尝试及错误

先编码再解码后强制类型转换:

_formKey.currentState?.save();

if (_formKey.currentState!.validate()) {
  if (_formKey
          .currentState
          ?.fields['date_required']
          ?.value !=
      null) {
    dateRequired = _formKey.currentState
        ?.fields['date_required']!.value;
  }

  Map<String, dynamic> data = {
    'date_required': dateRequired != null
        ? dateRequired!.formatDbDate()
        : null
  };

  String jsonString = jsonEncode(data);

  Map<String, dynamic> decodedMap =
      jsonDecode(jsonString);

  Map<String, String> dateRequiredString =
      decodedMap.cast<String, String>();

  print(data);

  print(dateRequiredString);

  uploadFile(
      context, user, dateRequiredString);
}

控制台报错(此时日期为null):

{date_required: null}
Error: Expected a value of type 'String', but got one of type 'Null'

5. 问题复现测试代码

import 'dart:convert';

void main() {
  Map<String, dynamic> data = {'date_required': null};

  print(data);

  String jsonString = jsonEncode(data);

  print(jsonString);

  Map<String, dynamic> decodedMap = jsonDecode(jsonString);

  print(decodedMap);

  Map<String, String> dateRequiredString = decodedMap.cast<String, String>();

  print(dateRequiredString);
}

控制台输出:

{date_required: null}
{"date_required":null}
{date_required: null}
: TypeError: null: type 'JSNull' is not a subtype of type 'String'Error: TypeError: null: type 'JSNull' is not a subtype of type 'String'

解决方案

由于MultipartRequest的fields仅支持String类型值,无法直接传递null,可采用以下三种方案解决:

方案1:调整Go API解析逻辑

在Go端接收字段时,判断字段是否为空字符串,将空字符串解析为null。Dart端对应处理:

// 有日期传格式化字符串,无则传空字符串
String dateValue = dateRequired?.formatDbDate() ?? '';
// 上传时直接赋值
request.fields['date_required'] = dateValue;

方案2:将JSON数据作为单独文本字段传递

把需要的JSON结构转成字符串,作为单个字段传入fields,Go端接收后直接解析该字符串:

// 生成含目标字段的JSON字符串
Map<String, dynamic> data = {
  'date_required': dateRequired?.formatDbDate()
};
String jsonPayload = jsonEncode(data);

// 上传时传递整个JSON字符串
request.fields['payload'] = jsonPayload;

方案3:添加JSON格式的MultipartPart

如果API支持,将JSON数据作为独立的MultipartPart添加到请求中,而非使用fields:

// 创建JSON数据的MultipartPart
final jsonPart = http.MultipartFile.fromString(
  'payload',
  jsonEncode(data),
  contentType: MediaType('application', 'json'),
);
request.files.add(jsonPart);

这种方式更贴近原始JSON请求格式,Go端可分别解析文件和JSON部分。

内容的提问来源于stack exchange,提问作者markhorrocks

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:07:51