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

如何用Dart以x-www-form-urlencoded格式提交嵌套结构数据?

解决嵌套结构转x-www-form-urlencoded的问题

你的问题出在直接对嵌套的数组/对象调用toString(),这会生成无法被服务端解析的无效字符串(比如[Instance of '_InternalLinkedHashMap<String, dynamic>'])。x-www-form-urlencoded对于嵌套结构需要按照层级键名的格式拼接,比如data[0][prefix]、data[0][phone]这类形式,和Postman里的提交逻辑一致。

下面是正确的递归转换实现:

String encodeNestedMap(Map<String, dynamic> map, [String parentKey = '']) {
  final parts = <String>[];

  map.forEach((key, value) {
    final currentKey = parentKey.isEmpty ? key : '$parentKey[$key]';

    if (value is Map<String, dynamic>) {
      // 递归处理嵌套Map
      parts.add(encodeNestedMap(value, currentKey));
    } else if (value is List) {
      // 处理数组,为每个元素添加索引标识
      for (var i = 0; i < value.length; i++) {
        final item = value[i];
        if (item is Map<String, dynamic>) {
          parts.add(encodeNestedMap(item, '$currentKey[$i]'));
        } else {
          // 非对象类型的数组元素直接编码
          parts.add(
            '${Uri.encodeQueryComponent('$currentKey[$i]')}=${Uri.encodeQueryComponent(item.toString())}'
          );
        }
      }
    } else {
      // 基础类型直接编码键值对
      parts.add(
        '${Uri.encodeQueryComponent(currentKey)}=${Uri.encodeQueryComponent(value.toString())}'
      );
    }
  });

  return parts.join('&');
}

// 使用示例
Map<String, dynamic> body = {
  'data': [
    {
      'prefix': '225',
      'phone': '1234567890',
      'email': 'test@gmail.com',
      'name': 'test',
      'surname': 'test',
    },
  ],
};

String bodyString = encodeNestedMap(body);
// 输出结果:data[0][prefix]=225&data[0][phone]=1234567890&data[0][email]=test%40gmail.com&data[0][name]=test&data[0][surname]=test

原方法失效原因

你之前的代码直接把entry.value(整个数组)转成字符串,得到的是类似[{prefix: 225, phone: 1234567890, ...}]的非标准格式,服务端无法识别。而递归处理会把每个嵌套字段拆成符合x-www-form-urlencoded规范的键值对,完全匹配Postman的提交逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:00:15