我有一个Flutter 应用程序,在其中我通常使用http请求从模型到Go API的请求发布,如下所示.

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

然而,我想同时上传文件和解码json数据.上传文件如下所示,但我从下面的代码中得到的结果是 或者(null),它会在我的API中抛出一个解码错误.我原以为是{"date_required": null}{"date_required": 2023-11-12}.

我怎么才能到那里呢?我注意到DART http使用Map<String, dynamic>,而DART MultipartRequest使用Map<String, String>,所以我可以使用NULL.这将需要在我的Go API中进一步解析.

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;

生成字段的DART代码,根据@mandy8055的答案进行编辑.

                                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'

进一步编辑:

                            _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);
                            }

这将抛出下面的错误(这里的日期应该为空).我看到 keys 没有被引用,但我认为它应该被引用.

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

以下是演示该问题的一些工作代码.我需要将Map<String, dynamic>转换为Map<String, String>,并保留"DATE_REQUIRED"键周围的引号.

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'

推荐答案

The key is to correctly transform and map the data types between Dart's Map<String, dynamic> and Map<String, String> (a bit as in this question).
You want to:

  • 与文件上载一起发送可为空的数据(date_required).
  • 保持Map<String, dynamic>Map<String, String>之间的兼容性.

try 将可为空的date_required转换为字符串表示形式.然后,确保正确处理null个值.

Future<dynamic> uploadFile(BuildContext context, User user, String? dateRequired) async {
    // existing setup code

    // Convert nullable date to a string representation
    String dateRequiredStr = dateRequired != null ? jsonEncode({'date_required': dateRequired}) : jsonEncode({'date_required': null});

    // Adding fields to the request
    request.fields['data'] = dateRequiredStr;

    // remaining code for file upload
}

使用jsonEncodeMap<String, dynamic>转换为String.将此JSON字符串直接赋给request.fields中的一个字段.


对于Go API,您需要将‘data’字段解析为JSON字符串并进行相应的处理.

import 'dart:convert';

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

  String jsonString = jsonEncode(data); // Convert map to JSON string

  print(jsonString); // {"date_required":null}

  // Directly use jsonString in your request.fields
  // Example: request.fields['data'] = jsonString;
}

// Note: There is no need to convert back to Map<String, String> in Dart.
// Handle the JSON parsing in your Go API.

Flutter相关问答推荐

Flutter 导致底部溢出

无法让Riverpod Stream发出新值

出现异常.RangeError(RangeError(index):无效值:有效值范围为空:0).分度误差

缩短经常使用的行Theme.of(context).colorScheme

在LinkedIn上分享Fighter和Web的链接会产生不同的结果

如何在Flutter 中共享选定文本

如何让两个展开的Widget根据其子窗口的屏幕大小

如何在Flutter中将背景 colored颜色 更改为黑色?

使用 forLoops 在 Dart 中进行单元测试会返回 stackoverflow

ScaffoldMessenger 在等待键下方不起作用

添加appBar时绘制的线条发生偏移 Flu

什么最接近 Dart 的 List.asMap().forEach() 返回列表?

如何从sibling ChildWidgetB 触发 ChildWidgetA 中的操作

如何在 cupertino switch flutter 中添加文本

type '({bool growable}) => List' 不是类型转换中类型 'List' 的子类型

如何从 Firebase `get()` 获取 `DocumentReference`

更改文本字段Flutter 中最大字母的 colored颜色

CircleAvatar 在 ListTile 中领先

Flutter:font_awesome_icon pro 版报错?如何设置 font_awesome 克隆仓库的路径?

如何在Flutter 中制作自定义微调器?