Skip to the code
cf.

Build a query string

Write toQueryString(params). It turns an object into a URL query string: key=value pairs joined with &, in the object's key order, with no leading ?.

Encode every key and value with encodeURIComponent, so a space becomes %20 (not +), and &, =, ?, #, /, and non-ASCII characters are percent-encoded as well.

Values are strings, numbers, booleans, null, undefined, or arrays of those. An array adds the key once per item, in order. Skip null and undefined, both as values and as array items, but keep 0, false, and "" (which gives key=). When there's nothing to add, return "".

toQueryString({ q: "red shoes", page: 2, tags: ["a", "b"], sort: undefined });
// "q=red%20shoes&page=2&tags=a&tags=b"

What the tests check

  1. joins key=value pairs with &
    expect(toQueryString({ a: "1", b: 2, c: true })).toBe("a=1&b=2&c=true");
    
  2. encodes spaces as %20, and reserved characters
    expect(toQueryString({ q: "red shoes & socks", "a b": "x=y/z?#" })).toBe("q=red%20shoes%20%26%20socks&a%20b=x%3Dy%2Fz%3F%23");
    
  3. encodes non-ASCII characters as UTF-8
    expect(toQueryString({ name: "José", city: "東京" })).toBe("name=Jos%C3%A9&city=%E6%9D%B1%E4%BA%AC");
    
  4. repeats the key for each array item
    expect(toQueryString({ tags: ["a", "b c"], page: 1 })).toBe("tags=a&tags=b%20c&page=1");
    expect(toQueryString({ none: [], x: 1 })).toBe("x=1");
    
  5. skips null and undefined, in arrays too
    expect(toQueryString({ a: null, b: undefined, c: "x", d: [1, null, 2, undefined] })).toBe("c=x&d=1&d=2");
    
  6. keeps 0, false, and empty strings
    expect(toQueryString({ zero: 0, no: false, empty: "" })).toBe("zero=0&no=false&empty=");
    
  7. returns an empty string when there's nothing to add
    expect(toQueryString({})).toBe("");
    expect(toQueryString({ a: null, b: [] })).toBe("");
    

Learn more

solution.jsSaved in this browser

Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.

Ctrl + Enter runs the tests (⌘ + Enter on a Mac).