Как сделать запрос HTTP POST с закодированным текстом теле в флаттер?

Я пытаюсь сделать запрос на отправку с типом контента с кодировкой url. Когда я пишу body: json.encode(data), он кодируется в обычный текст.

Если я пишу body: data я получаю type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String' in type cast ошибки type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String' in type cast

Это объект данных

var match = {
  "homeTeam": {"team": "Team A"},
  "awayTeam": {"team": "Team B"}
};

И моя просьба

var response = await post(Uri.parse(url),
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: match,
    encoding: Encoding.getByName("utf-8"));

Ответы

Ответ 1

Вам нужно добавить три дополнительных шага: сначала вам нужно преобразовать json-карту в String (используя json.encode). Затем вам нужно закодировать Uri, если вы хотите отправить его как application/x-www-form-urlencoded. Наконец, вам нужно указать параметр, по которому вы отправляете имя.

Например (обратите внимание, что это использование дротика: io HttpClient, но это в основном то же самое):

  Future<HttpClientResponse> foo() async {
    Map<String, dynamic> jsonMap = {
      'homeTeam': {'team': 'Team A'},
      'awayTeam': {'team': 'Team B'},
    };
    String jsonString = json.encode(jsonMap); // encode map to json
    String paramName = 'param'; // give the post param a name
    String formBody = paramName + '=' + Uri.encodeQueryComponent(jsonString);
    List<int> bodyBytes = utf8.encode(formBody); // utf8 encode
    HttpClientRequest request =
        await _httpClient.post(_host, _port, '/a/b/c');
    // it polite to send the body length to the server
    request.headers.set('Content-Length', bodyBytes.length.toString());
    // todo add other headers here
    request.add(bodyBytes);
    return await request.close();
  }

Вышесказанное относится к дроти: версия io (которую, конечно же, можно использовать в Flutter). Если вы хотите придерживаться пакета: http-версия, то вам нужно немного настроить карту. Тело должно быть Map <String, String>. Вам нужно решить, что вы хотите в качестве параметров POST. Вы хотите два: homeTeam и awayTeam? или, скажем, teamJson?

Этот код

  Map<String, String> body = {
    'name': 'doodle',
    'color': 'blue',
    'homeTeam': json.encode(
      {'team': 'Team A'},
    ),
    'awayTeam': json.encode(
      {'team': 'Team B'},
    ),
  };

  Response r = await post(
    url,
    body: body,
  );

производит это на проводе

Имя = & каракули цвет = синий & homeTeam =% 7B% 22team% 22% 3A% 22Team + А% 22% 7D & awayTeam =% 7B% 22team% 22% 3A% 22Team + B% 22% 7D

альтернативно, это

  Map<String, String> body = {
    'name': 'doodle',
    'color': 'blue',
    'teamJson': json.encode({
      'homeTeam': {'team': 'Team A'},
      'awayTeam': {'team': 'Team B'},
    }),
  };

  Response r = await post(
    url,
    body: body,
  );

производит это на проводе

Имя = каракули & цвет = синий & teamJson =% 7B% 22homeTeam% 22% 3A% 7B% 22team% 22% 3A% 22Team + А% 22% 7D% 2C% 22awayTeam% 22% 3A% 7B% 22team% 22% 3A% 22Team + В % 22% 7D% 7D

пакет: клиент http заботится: кодирование Uri.encodeQueryComponent, кодировка utf8 (обратите внимание, что это значение по умолчанию, поэтому нет необходимости указывать его) и отправки длины в заголовке Content-Length. Вы все равно должны выполнить кодировку json.

Ответ 2

Я бы хотел порекомендовать вам пакет dio, dio - мощный Http-клиент для Dart/Flutter, который поддерживает перехватчики, FormData, отмену запросов, загрузку файлов, тайм-аут и т.д.

dio очень прост в использовании, в вашем случае вы можете:

Map<String, String> body = {
'name': 'doodle',
'color': 'blue',
'teamJson': {
  'homeTeam': {'team': 'Team A'},
  'awayTeam': {'team': 'Team B'},
  },
};

dio.post("/info",data:body, options: 
  new Options(contentType:ContentType.parse("application/x-www-form-urlencoded")))    

dio может автоматически кодировать данные.

Более подробная информация, пожалуйста, обратитесь к дио.

Ответ 3

вам нужно использовать json.encode

пример;

var match = {
  "homeTeam": {"team": "Team A"},
  "awayTeam": {"team": "Team B"}
};
var response = await post(Uri.parse(url),
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: json.encode(match),
    encoding: Encoding.getByName("utf-8"));

Ответ 4

Код ниже - это функция, которую я создал для отправки запроса POST

Future<http.Response> postData(String url, Map<String, dynamic> data) async {
Map<String, String> headers = await _getHeaders();

http.Response response = await http.post(
  Uri.parse(kBaseUrl + url),
  headers: headers,
  body: data,
  encoding: Encoding.getByName('utf-8'),
);

return response;
}

Код ниже является примером использования

Map<String, dynamic> authData = {
    "email": "testsdsd",
    "password": "sdsdsd",
  };

  // send an auth request to the API
  http.Response response = await _networkService.postData(
    'authenticate',
    authData,
  );

Ответ 5

Я пришел сюда, просто пытаясь сделать HTTP-запрос POST. Вот пример того, как это сделать:

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


makePostRequest() async {

  final uri = 'http://httpbin.org/post';
  final headers = {'Content-Type': 'application/json'};
  Map<String, dynamic> body = {'id': 21, 'name': 'bob'};
  String jsonBody = json.encode(body);
  final encoding = Encoding.getByName('utf-8');

  Response response = await post(
    uri,
    headers: headers,
    body: jsonBody,
    encoding: encoding,
  );

  int statusCode = response.statusCode;
  String responseBody = response.body;
}