Dart HTTP POST,其中Map <string,dynamic =“”>作为正文

时间:2019-02-08 19:15:18

标签: json dart flutter

Dart http packagepost方法仅接受StringList<int>Map<String, String>作为请求 body 。 我需要使用Content-Type标头application / json将此类的对象发送为主体:

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

ListingImage在哪里

class ListingImage {
  String url;
  int position;
}

在邮递员中,我将使用Content-Type标头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>

请帮助。

5 个答案:

答案 0 :(得分:2)

使用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,一组表单字段或图像。它知道如何根据标头和任何指定的编码来执行此操作。

答案 1 :(得分:1)

我在搜索如何使用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);
}

答案 2 :(得分:0)

有一个dart程序包,它为http请求提供了一些帮助程序类,以及一个有助于json序列化的程序包。

BasicUtils: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);

答案 3 :(得分:0)

如果您需要将复杂的数据作为 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

答案 4 :(得分:0)

就我而言,我收到了 400 错误。我有这种类型的帖子正文

Map<String, dynamic> requestBodyMap = {"user":{"email":"test@test.com","password":"123456"}};

我使用

对其进行了编码
String requestBody = json.encode(requestBodyMap);

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