如何在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
相关产品推荐
相关产品推荐

