如何向 Dart http 请求添加查询参数?

如何正确地向 Dart http 获取请求添加查询参数?我无法让我的请求正确响应时,试图附加’?Param1 = one & param2 = two’to my url,但它在 Postman 中工作正常。以下是我的代码要点:

    final String url = "https://www.myurl.com/api/v1/test/";
String workingStringInPostman = "https://www.myurl.com/api/v1/test/123/?param1=one&param2=two";


Map<String, String> qParams = {
'param1': 'one',
'param2': 'two',
};




var res = await http
.get(Uri.encodeFull("$url${widget.pk}/"),
headers: {HttpHeaders.authorizationHeader: "Token $token",
HttpHeaders.contentTypeHeader: "application/json"},
);

${ widget.pk }只是一个正在传递的整数值(参见 workingStringInPostman 变量中的值123。

QParams 是为了方便使用,以防需要 Uri 参数。

欢迎使用代码示例。

121926 次浏览

You'll want to construct a Uri and use that for the request. Something like

final queryParameters = {
'param1': 'one',
'param2': 'two',
};
final uri =
Uri.https('www.myurl.com', '/api/v1/test/${widget.pk}', queryParameters);
final response = await http.get(uri, headers: {
HttpHeaders.authorizationHeader: 'Token $token',
HttpHeaders.contentTypeHeader: 'application/json',
});

See https://api.dartlang.org/stable/2.0.0/dart-core/Uri/Uri.https.html

There is a dart package that provides some helper classes for http requests.

BasicUtils : https://github.com/Ephenodrom/Dart-Basic-Utils

Install it with:

dependencies:
basic_utils: ^1.4.0

Usage

You can add a map of headers and query parameters to each request. See the example :

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


// Body
String body = "{ 'some':'json'}";


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

Additional information :

These are all methods from the HttpUtils class.

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

The accepted answer didn't work for me but adding a '&' without quotes to end of the URL solves my problem. In this case, change the following line:

String workingStringInPostman = "https://www.myurl.com/api/v1/test/123/?param1=one&param2=two";

to this: (Notice the '&' at the end).

String workingStringInPostman = "https://www.myurl.com/api/v1/test/123/?param1=one&param2=two&";

Got the same question. The accepted answer won't work if my url is localhost with port like https://localhost:5001. After spending 1 day to search for solution, I come up with Dio library. Following is my solution using Dio:

var _dio = new Dio();
var options = new Options;
options.headers['Authorization'] = 'bearer $token';
options.contentType = 'application/json';
String url = "https://www.myurl.com";
Map<String, String> qParams = {
'param1': 'one',
'param2': 'two',
};


var res = await _dio.get(url, options: options, queryParameters: qParams);

Hope this helps.

Use Uri constructor to build your query, it has a queryParameter property.

var uri = Uri(
scheme: 'https',
host: 'example.com',
path: '/foo/bar',
fragment: 'baz',
queryParameters: _yourQueryParameters,
);


var response = await http.get(uri);
if (response.statusCode == 200) {
var json = jsonDecode(response.body);
// Do whatever you want to do with json.
}

If you dont want to override the scheme of base endpoint url, use the below technique to convert the map to query string and append it to the base endpoint url

var endpointUrl = 'https://www.myurl.com/api/v1/user';
Map<String, String> queryParams = {
'param1': '1',
'param2': '2'
};


var headers = {
HttpHeaders.authorizationHeader: 'Token $token',
HttpHeaders.contentTypeHeader: 'application/json',
}


String queryString = Uri.parse(queryParameters: queryParams).query;


var requestUrl = endpointUrl + '?' + queryString; // result - https://www.myurl.com/api/v1/user?param1=1&param2=2
var response = await http.get(requestUrl, headers: headers);

I made a little util function which resolves the authority / unencodedPath parameters for Uri creation.

Uri createUri(String url, [Map<String, String> queryParameters]) {
var isHttp = false;
if (url.startsWith('https://') || (isHttp = url.startsWith('http://'))) {
var authority = url.substring((isHttp ? 'http://' : 'https://').length);
String path;
final index = authority.indexOf('/');


if (-1 == index) {
path = '';
} else {
path = authority.substring(index);
authority = authority.substring(0, authority.length - path.length);
}


if (isHttp) {
return Uri.http(authority, path, queryParameters);
} else {
return Uri.https(authority, path, queryParameters);
}
} else if (url.startsWith('localhost')) {
return createUri('http://' + url, queryParameters);
}


throw Exception('Unsupported scheme');
}

Here is the example code which uses it:

final String url = 'https://www.myurl.com/api/v1/test/${widget.pk}';
Map<String, String> qParams = {
'param1': 'one',
'param2': 'two',
};


var res = await http.get(
createUri(url, qParams),
headers: {
HttpHeaders.authorizationHeader: "Token $token",
HttpHeaders.contentTypeHeader: "application/json"
},
);

Use Uri to pass query parameters like.

final String url = "https://www.myurl.com/api/v1/test/${widget.pk}/";


Map<String, String> qParams = {
'param1': 'one',
'param2': 'two',
};
Map<String, String> header = {
HttpHeaders.authorizationHeader: "Token $token",
HttpHeaders.contentTypeHeader: "application/json"
};


Uri uri = Uri.parse(url);
final finalUri = uri.replace(queryParameters: qParams); //USE THIS


final response = await http.get(
finalUri,
headers: header,
);

this is more simple

final uri = Uri.parse('$baseUrl/v1/endpoint').replace(queryParameters: {
'page': page,
'itemsPerPage': itemsPerPage,
});
final response = await client.get(uri);

The following function copied from flutter code can be used to create the query string part only:

String queryString(Map<String, dynamic> queryParameters) {
var result = StringBuffer();
var separator = "";


void writeParameter(String key, String? value) {
result.write(separator);
separator = "&";
result.write(Uri.encodeQueryComponent(key));
if (value != null && value.isNotEmpty) {
result.write("=");
result.write(Uri.encodeQueryComponent(value));
}
}


queryParameters.forEach((key, value) {
if (value == null || value is String) {
writeParameter(key, value);
} else {
Iterable values = value;
for (String value in values) {
writeParameter(key, value);
}
}
});
return result.toString();
}

Usage:

var q = queryString({"a":"b&", "c":["1","xyz"]});
// a=b%26&c=1&c=xyz

U can use this:

String _getParamsFromBody( Map<String, dynamic>? body) {
String params = '?';
for (var i = 0; i < body!.keys.length; i++) {
params += '${List.from(body!.keys)[i]}=${List.from(body!.values)[i]}';
if (i != body!.keys.length - 1) {
params += '&';
}
}
log(params);
return params;

}

Uri.parse("https://www.myurl.com/api/v1/test"+ _getParamsFromBody({'param1':'value1','param2':'value2}))