使用Map< String,dynamic>作为主体的Dart HTTP POST

8ljdwjyq  于 2023-09-28  发布在  其他
关注(0)|答案(5)|浏览(86)

Dart http packagepost方法只接受StringList<int>Map<String, String>作为请求body。我需要将这个类的对象作为body发送,并带有Content-Type头application/json:

class CreateListingRequest {
  String title;
  List<ListingImage> images;
  List<int> categoryIds;
}

其中ListingImage

class ListingImage {
  String url;
  int position;
}

在Postman中,我会将body构建为带有Content-Type header application/json的原始json,如下所示:

{
  "title": "Testing transaction force fail",
  "listing_images": [
    {
      "url": "https://picsum.photos/500/500/?image=336",
      "position": 0
    },
    {
      "url": "https://picsum.photos/500/500/?image=68",
      "position": 1
    },
    {
      "url": "https://picsum.photos/500/500/?image=175",
      "position": 2
    }
  ],
  "category_ids": [19, 26]
}

在我看来,如果我可以发送一个Map<String, dynamic>,将解决这个问题,但我只能发送Map<String, String>
请帮帮我

uelo1irk

uelo1irk1#

使用String encoded = json.encode(theMap);然后发布encoded。如果您需要特定的字符编码(例如utf-8),然后使用utf8.encode(encoded)进一步编码字符串,并发布结果字节数组。(第二步对于utf-8应该是不必要的,因为我认为这是默认的。)
值得考虑的是这三种变体的作用:

  • List<int>-发送不透明字节数组
  • String使用字符编码将字符串编码为字节,并发送字节数组
  • Map<String, String>-将字符串键/值对编码到x-www-form-urlencoded中并发送。

如果你想发送更复杂的数据,那么你需要将其转换为上述之一(服务器需要知道如何解码)。这就是content-type头文件的用处所在。最终,服务器接收到一个字节数组,并将其转换回字符串、JSON、表单字段集或图像。它知道如何根据头和任何指定的编码来执行此操作。

ijxebb2r

ijxebb2r2#

我在搜索如何用List<Map<String, dynamic>>发送POST请求时发现了这个问题。经过一番思考,我编写了代码来实现这个目标。它也适用于初始问题(您只需要将函数的参数设置为Map<String, dynamic>类型)。

import 'package:http/http.dart' as http;
import 'dart:convert';

//...

static const Map<String, String> _JSON_HEADERS = {
    "content-type": "application/json"
  };

void sendPost(List<Map<String, dynamic>> data) {
  http.Client client = new http.Client();
  final String encodedData = json.encode(data);
  client.post(ADDRESS, //your address here
              body: encodedData, headers: _JSON_HEADERS);
}
nfs0ujit

nfs0ujit3#

如果需要将复杂的数据作为POST请求的主体发布,也就是说,将其作为对象本身发布,而不是作为服务器必须在其结束时再次解码的JSON编码字符串发布,则可以使用Flutter包Dio而不是http。我刚刚发布了这个:

import 'package:dio/dio.dart';

                  Response res;
                  Dio dio = new Dio();
                  try {
                    res = await dio.post('<url>', data: {
                      "Body": {
                        "stkCallback": {
                          "MerchantRequestID": "21605-295434-4",
                          "CheckoutRequestID": "ws_CO_04112017184930742",
                          "ResultCode": '0',
                          "ResultDesc": "The service request is processed successfully.",
                          "CallbackMetadata": {
                            "Item": [
                              {"Name": "Amount", "Value": 1},
                              {"Name": "MpesaReceiptNumber", "Value": "LK451H35OP"},
                              {"Name": "Balance"},
                              {"Name": "TransactionDate", "Value": 20171104184944},
                              {"Name": "PhoneNumber", "Value": 254727894083}
                            ]
                          }
                        }
                      }
                    });
                  } catch (e) {
                    print('Caught an error in API call!');
                    print('e is: ${e.toString()}');
                    Alert(context: context, title: 'Http POST error', desc: '$e').show();
                    if (res != null) print('Status code in apiCall() catch is ${res.statusCode}');
                  }

下面是Dio包:https://pub.dev/packages/dio

zi8p0yeb

zi8p0yeb4#

在我的情况下,我得到了一个400错误。我有那种类型的后体

Map<String, dynamic> requestBodyMap = {"user":{"email":"[email protected]","password":"123456"}};

我把它编码成

String requestBody = json.encode(requestBodyMap);

并在邮件请求中发送了这具尸体问题是由于标题中的内容类型,它在标题中采用application/x-www-form-urlencoded类型。我将其更改为application/json类型,然后响应成功。接受参数也有application/json

idv4meu8

idv4meu85#

有一个dart包提供了一些http请求的帮助类,还有一个包帮助json序列化。
基本实用程序:https://github.com/Ephenodrom/Dart-Basic-Utils
JsonSerializable:https://flutter.dev/docs/development/data-and-backend/json
安装它与:

dependencies:
  basic_utils: ^1.4.0
  json_annotation: ^2.0.0

dev_dependencies:
  test: '>=0.12.42 <2.0.0'
  build_runner: ^1.0.0
  json_serializable: ^2.0.0

使用
像这样更新你的类:

import 'package:json_annotation/json_annotation.dart';

part 'CreateListingRequest.g.dart';

@JsonSerializable()
class CreateListingRequest {
  String title;
  List<ListingImage> images;
  List<int> categoryIds;

  factory CreateListingRequest.fromJson(Map<String, dynamic> json) =>
      _$CreateListingRequestFromJson(json);

  Map<String, dynamic> toJson() => _$CreateListingRequestToJson(this);
}

import 'package:json_annotation/json_annotation.dart';

part 'ListingImage.g.dart';

@JsonSerializable()
class ListingImage {
  String url;
  int position;

  factory ListingImage.fromJson(Map<String, dynamic> json) =>
      _$ListingImageFromJson(json);

  Map<String, dynamic> toJson() => _$ListingImageToJson(this);
}

使用以下命令创建 *.g.dart文件:

pub run build_runner build

现在您的工作区中有了一些 *.g.dart文件。之后,您可以使用您的类为您的http请求。

//Convert class to string
String body = json.encode(payload.toJson());

// Convert response to class
MyResponseClass responseAsClass = MyResponseClass.fromJson(responseData);

完整示例

// Define some headers and query parameters
Map<String, String> headers = {
  "Accept": "application/json"
};
Map<String, String> queryParameters = {
  "foo": "bar"
};

// Create instance of the class
CreateListingRequest payload = CreateListingRequest();

// Convert class to String
String body = json.encode(payload.toJson()); // that does the magic :)

// Send request
Map<String, dynamic> responseData = await HttpUtils.postForJson("api.com/dosomething", body,
      headers: headers, queryParameters: queryParameters);

// Convert response to class
MyResponseClass responseAsClass = MyResponseClass.fromJson(responseData);

其他信息:
这些都是HttpUtils类中的方法。

Future<Map<Response> getForFullResponse(String url,{Map<String, dynamic> queryParameters,Map<String, String> headers});
Future<Map<String, dynamic>> getForJson(String url,{Map<String, dynamic> queryParameters,Map<String, String> headers});
Future<String> getForString(String url,{Map<String, dynamic> queryParameters,Map<String, String> headers});
Future<Map<Response> postForFullResponse(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Map<String, dynamic>> postForJson(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<String> postForString(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Response> putForFullResponse(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Map<String, dynamic>> putForJson(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<String> putForString(String url, String body,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Response deleteForFullResponse(String url,{Map<String, String> queryParameters,Map<String, String> headers});
Future<Map<String, dynamic>> deleteForJson(String url,{Map<String, String> queryParameters,Map<String, String> headers});
Future<String> deleteForString(String url,{Map<String, String> queryParameters,Map<String, String> headers});
Map<String, dynamic> getQueryParameterFromUrl(String url);
String addQueryParameterToUrl(String url, Map<String, dynamic> queryParameters);

相关问题