Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customizing Date Serialization in Axios

By default, when a JavaScript object contains a Date object, Axios serializes it into UTC. This means that the time transmitted is converted using the time zone. This doesn't work for my use case. I need to send the time without the time zone conversion to UTC.

I implemented a custom serializer based on #1548, but it has no effect. I have verified that the config is being modified, but when I look at the request payload, the dates are still using UTC (2022-02-03T04:59:00.000Z).

Note: My logic is more complicated, I am using toLocalString() in the code below to simplify the example.

const a = axios.create()
a.interceptors.request.use((config) => {
  config.paramsSerializer = (params) =>
    qs.stringify(params, {
      serializeDate: (date: Date) => date.toLocaleString(),
    })
  return config
})

Anyone understand why I can't override the default behavior and use my own date formatting?

Environment Axios Version 0.21.1

like image 978
Cindy Conway Avatar asked Dec 07 '25 03:12

Cindy Conway


1 Answers

It's not Axios doing the serialisation. Date implements toJSON() which is employed when your objects (containing dates) are serialised via JSON.stringify()...

The instances of Date implement the toJSON() function by returning a string (the same as date.toISOString()). Thus, they are treated as strings.

The paramSerializer is for serialising query params which is why it didn't apply to your request body.

To transform the request body, you want to use transformRequest.

Here's a generic, recursive transformer that finds dates and maps them to localised strings

import axios, { AxiosRequestTransformer } from 'axios';

const isPlainObject = (v: unknown) =>
  Object.prototype.toString.call(v) === '[object Object]';

const dateTransformer: AxiosRequestTransformer = (data) => {
  if (data instanceof Date) {
    // do your specific formatting here
    return data.toLocaleString();
  }
  if (Array.isArray(data)) {
    return data.map((val) => dateTransformer(val));
  }
  if (isPlainObject(data)) {
    return Object.fromEntries(
      Object.entries(data).map(([key, val]) => [key, dateTransformer(val)]),
    );
  }
  return data;
};

You can then register this transformer in your Axios instance which will apply to all PUT, POST, PATCH and DELETE requests.

const instance = axios.create({
  transformRequest: [ dateTransformer ].concat(axios.defaults.transformRequest)
})

instance.post(url, data)

If the generic version seems a little heavy-handed, you can either transform the object yourself before posting...

const body = {
  date: new Date()
}

axios.post(url, {
  ...body,
  date: body.date.toLocaleString()
})

or register an inline transformer

axios.post(url, body, {
  transformRequest: [
    data => ({
      ...data,
      date: data.date.toLocaleString()
    }),
    ...axios.defaults.transformRequest
  ]
})
like image 133
Phil Avatar answered Dec 08 '25 18:12

Phil



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!