0

I need to map a JavaScript object to query string parameters. I found several related questions on this site, but none that fully met my needs.

The object will consist of strings and arrays, but will not be nested. Here is an example:

var filters = {
    make: ["Ford", "Honda"],
    year: [],
    color: "Black",
    model: ""
}

Here is the code I have:

mapQueryStringParameters = function (params) {
    return params
        ? '?' + Object.entries(params)
            .flatMap(([key, value]) => [value].flat().map(v => [key, v]))
            .map(it => it.join("="))
            .join("&")
        : "";
}

The above code produces the following result, which is almost correct:

"?make=Ford&make=Honda&color=Black&model="

It correctly omits the year empty array, but adds an property for model, which is an empty string. How can I modify so that it omits any property with an empty string?

2

3 Answers 3

2

After flat() inject this filter

.filter(v => v !== "")

...and continue with the rest of your chain.

Note that params will be truthy when it is just {}, so if you don't want to generate the ? character in that case, you'll need a different logic. Possibly generate the "?" and then remove it if nothing else followed it. Then it will also not generate the "?" when you pass in a non-empty object, but with its properties all set to an empty string:

mapQueryStringParameters = function (params) {
    return ('?' + Object.entries(params)
              .flatMap(([key, value]) => 
                [value].flat()
                       .filter(v => v !== "")
                       .map(v => [key, v]))
                       .map(it => it.join("=")
               )
              .join("&")
          ).replace(/^.$/, "") // Remove lonely "?"
}

var filters = {
    make: ["Ford", "Honda"],
    year: [],
    color: "Black",
    model: ""
}

const query = mapQueryStringParameters(filters);
console.log(query);

Sign up to request clarification or add additional context in comments.

3 Comments

Or also .filter(Boolean) (edit: if you only use strings as values)
Yes, but then you'll also filter out 0 or false, ...
Indeed, but AFAICS OP's values seem always strings. But yeah. Good notice.
1

First I would clean the obejct with:

Object.keys(obj).forEach(key => {
  if (obj[key] === '' || obj[key].length === 0) {
    delete obj[key];
  }
});

Then build the URL with:

const obj = {
  make: 'Nissan',
  color: ['yellow', 'orange', 'blue'],
};

const result = '?' + new URLSearchParams(obj).toString();
console.log(result); // 👉️ '?make=Nissan&color=yellow%2Corange%2Cblue'

1 Comment

But that's not the output they want for arrays with multiple entries.
0

You could filter first and then get the string.

const
    filters = { make: ["Ford", "Honda"], year: [], color: "Black", model: "" },
    temp = Object
        .entries(filters)
        .filter(([, v]) => v !== '')
        .flatMap(([k, v]) => [].concat(v).map(e => `${k}=${e}`))
        .join('&'),
    result = (temp && '?') + temp;

console.log(result);

1 Comment

Except query strings are delimited by & characters, not ;. and the initial character should be ?.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.