Skip to content

Support deep object notation like Axios #887

@josephdpurcell

Description

@josephdpurcell

What would you like to see in the library?

I phrase this as a feature request, not a bug, because Gaxios only claims to be Axios-like and clearly states that query params are passed to URLSearchParams.

This feature request is to support deep object notation in the same way that Axios does. While there is no formal specification for deep object notation (also known as nested objects) it is widely used, such as Express (qs), PHP, etc.

Axios supports deep object notation. Here is an example test that could be added to Axios that passes:

it("should support deep object notation", function (done) {
  axios.get("/foo", {
    params: {
      foo: {
        bar: "baz",
      },
    },
  });
  getAjaxRequest().then(function (request) {
    expect(request.url).toBe("/foo?foo%5Bbar%5D=baz");
    done();
  });
});

A similar test would fail in Gaxios, for example if you add the following test to test/test.getch.ts:

it('should support deep object notation parameters', async () => {
  const opts = {
    url,
    params: {starfleet: {james: 'kirk', montgomery: 'scott'}},
  };
  const qs = '?starfleet[james]=kirk&starfleet[montgomery]=scott';
  const path = `/${qs}`;
  const scope = nock(url).get(path).reply(200, {});
  const res = await request(opts);
  assert.strictEqual(res.status, 200);
  assert.strictEqual(
    res.config.url?.toString(),
    new URL(url + qs).toString(),
  );
  scope.done();
});

This test fails. Because the config.params is passed to URLSearchParams (see code) it gets clobbered. As a quick example run:

for (const [key, value] of new URLSearchParams({ foo: { bar: 'baz' }})) { console.log(key, value) }

And you'll get foo [object Object].

As best I can tell Axios uses its own deep object serialization leveraging JavaScript's FormData. Look at https://github.com/axios/axios/blob/v1.x/lib/helpers/AxiosURLSearchParams.js#L29.

So, if Gaxios were to support deep object notation it may be best to follow a similar approach to Axios given the issues qs may cause, see also #759.

Why wouldn't Gaxios support this? I think OAI/OpenAPI-Specification#1706 (comment) offers good reflection on the challenges here, namely that there are many serialization approaches that could be desired, deep object notation (which again isn't a formal standard) is just one of them.

Perhaps this feature request, then, is to offer an out-of-the-box option to have query string serialization be compatible with Axios. This allows implementers to use Gaxios as a drop-in replacement for Axios when deep object notation is used.

Describe alternatives you've considered

The concept of a workaround to this can be seen here using qs:

if (config?.params) {
  const queryString = qs.stringify(config.params, { encode: false });
  config.params = qs.parse(queryString, { depth: 0 });
}

Additional context/notes

No response

Edit: fix whitespace

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions