Reputation: 56934
I have a situation where I need to turn a Map
into a query String (after the first ?
). For instance if I have the following map:
Map json = {
"email": eml,
"password": passwd
};
And a base URL:
String baseURL = "http://localhost:8080/myapp";
Then I need something that converts the json Map
into the query string of the base URL:
String fullURL = parameterizeURL(baseURL, json);
// Prints: http://localhost:8080/myapp?email=blah&password=meh
// (if "blah" was entered as the email, and "meh" was entered as the password)
print(fullURL);
I found this query String-to-map library on Git, but I need the inverse of this! It would be great to get URL encoding in there as well.
I'm happy to make something homegrown but being so new to Dart I was wondering if there's anything on pub
/Github/the etherspehere that does this already.
Upvotes: 31
Views: 13981
Reputation: 4808
This is my own function that will escape the parameters that have null value
String generateQueryString(Map<String, dynamic> params) {
List queryString = [];
params.forEach((key, value) {
if (value != null) {
queryString.add(key + '=' + value.toString());
}
});
return queryString.join('&');
}
String query = generateQueryString({
'CategoryId': '1',
'MinAmount': 0,
'MaxAmount': 2012,
'Quantity': 1,
});
print(query); // CategoryId=1&MinAmount=0&MaxAmount=2012&Quantity=1
Upvotes: 1
Reputation: 90125
I think that the easiest way to to generate a query string from a Map
is to use Uri.replace
. It's basically the same thing as using the Uri
constructor, but it avoids needing to manually copy all of the other parts of the URL:
String baseURL = "http://localhost:8080/myapp";
Map json = {
"email": eml,
"password": passwd
};
String fullURL = Uri.parse(baseURL).replace(queryParameters: json).toString();
I realize that I'm responding to an old question, but I feel compelled to additionally point out that you probably shouldn't be sending passwords via query strings.
Upvotes: 2
Reputation: 1229
I faced the same problem and wrote this function for me. Here it is in case someone needs it:
String makeQuery(Map<String, dynamic>? data) {
var result = [];
if (data != null) {
data.forEach((key, value) {
if (value != null && (value is! String || value.trim().isNotEmpty)) {
result.add('$key=${value.toString()}');
}
});
}
return result.join('&');
}
Upvotes: 1
Reputation: 81
final yourMap = {'x': '1', 'y': '2'};
final queryString = yourMap.toMap().entries.map((e) => '${e.key}=${e.value}').join('&');
print(queryString); // x=1&y=2
Upvotes: 7
Reputation: 9937
Just in case if you use the Dio library, you might use Transformer.urlEncodeMap. It accepts Map<String, dynamic>
String Transformer.urlEncodeMap(Map<String, dynamic>)
You can find it in the official docs here: https://pub.dev/documentation/dio/latest/dio/Transformer/urlEncodeMap.html
Upvotes: 2
Reputation: 2183
TL;DR
String queryString = Uri(queryParameters: {'x': '1', 'y': '2'}).query;
print(queryString); // x=1&y=2
Upvotes: 31
Reputation: 907
i wrote a recursive function to turn any Map<String, dynamic>
to query String
.
String getQueryString(Map params, {String prefix: '&', bool inRecursion: false}) {
String query = '';
params.forEach((key, value) {
if (inRecursion) {
key = '[$key]';
}
if (value is String || value is int || value is double || value is bool) {
query += '$prefix$key=$value';
} else if (value is List || value is Map) {
if (value is List) value = value.asMap();
value.forEach((k, v) {
query += getQueryString({k: v}, prefix: '$prefix$key', inRecursion: true);
});
}
});
return query;
}
example:
Map<String, dynamic> params = {'aa': 1.1, 'bb': [2, [3, ['5', {'66': 777}]]]};
String query = getQueryString(params);
print(query);
this code will print:
&aa=1.1&bb[0]=2&bb[1][0]=3&bb[1][1][0]=5&bb[1][1][1][66]=777
Upvotes: 4
Reputation: 1069
Have you looked at the Uri class in dart:core. You can construct a Uri class from Url components :
new Uri({String scheme, String userInfo: "", String host: "", port: 0, String path,
Iterable<String> pathSegments, String query,
Map<String, String> queryParameters, fragment: ""}) #
Notice you pass the query string as a map, if you are using a HTTP client that doesn't take this class you can .toString it to get the Url.
I use this in my code rather than string Url's
As an example using your data above :
void main() {
String eml = "[email protected]";
String passwd = "password";
Map json = {
"email": eml,
"password": passwd
};
Uri outgoingUri = new Uri(scheme: 'http',
host: 'localhost',
port: 8080,
path: 'myapp',
queryParameters:json);
print(outgoingUri);
}
This prints :
http://localhost:8080/myapp?email=me%40here.com&password=password
Note that once constructed a Uri is immutable, i.e. you can't change the query parameters again. There is also this package in pub which may give more facilities although I've not used it yet.
Upvotes: 27
Reputation: 6312
Can you describe your usage a bit? First off, keeping data such as password in a GET request is not good practice. This is something that would better off being a POST request. That said, if you do want to use it as a POST request to send the map the server, take a look at: HttpRequest.postFormData it will automatically add the Map you provide as the POST data to the server. One caveat to remember is that data must be a Map (or keys and values must be strings). Example usage:
import 'dart:html';
// ...
// Somewhere in your login related method
HttpRequest.postFormData('login.php', data).then((HttpRequest req) {
if(req.status != 200) {
print(req.statusText);
}
});
There is a package available for server-side Dart which allows you to easily compose hand deal with various HTTP request, aptly named http. However this does not work with Client side scripts. I'm not aware of any existing packages which would provide the functionality you're looking for.
On that note, if you do decide to roll your own, perhaps provide a pull request to the QueryString project you mentioned in your question so that functionality can become available to others in one simple package.
Upvotes: 0