IAmYourFaja
IAmYourFaja

Reputation: 56934

Dart: convert map into query string

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

Answers (9)

Dhairya Lakhera
Dhairya Lakhera

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

jamesdlin
jamesdlin

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

Next Developer
Next Developer

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

David Araujo
David Araujo

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

channa ly
channa ly

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

Alex Kalmikov
Alex Kalmikov

Reputation: 2183

TL;DR

String queryString = Uri(queryParameters: {'x': '1', 'y': '2'}).query;

print(queryString); // x=1&y=2

Upvotes: 31

Roi Dayan
Roi Dayan

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

user2685314
user2685314

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

Matt B
Matt B

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

Related Questions