Integrating Fast JSON Parsers into Axios

By default, the Axios HTTP client utilizes JavaScript's native JSON.parse method to deserialize response data. While native parsing is suitable for standard workloads, high-throughput applications or systems processing massive JSON payloads can benefit from replacing the default deserializer with optimized or specialized libraries like fast-json-parse, destr, or json-bigint. This article explains how to override the default JSON parsing mechanism in Axios using custom response transformers.

Why Replace the Default Parser?

Replacing native JSON.parse in Axios is typically done for three reasons:

  1. Performance: Libraries like fast-json-parse reduce parsing overhead for heavy data streams.
  2. Security: Parsers like secure-json-parse protect applications against prototype pollution attacks.
  3. Data Integrity: Packages like json-bigint prevent precision loss when dealing with 64-bit integers that JavaScript's native Number type cannot represent.

Overriding the Parser with transformResponse

Axios allows modification of the response pipeline via the transformResponse configuration option. By providing a custom function to this array, you can intercept the raw string payload and apply your preferred parser before the data reaches your application logic.

1. Integrating fast-json-parse

The fast-json-parse library wraps parsing logic to optimize performance and avoids try/catch de-optimizations by returning an object containing either the parsed value or an err.

npm install fast-json-parse axios
import axios from 'axios';
import parse from 'fast-json-parse';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  transformResponse: [
    (data) => {
      // Axios may pass non-string data (e.g., if already parsed or empty)
      if (typeof data !== 'string') {
        return data;
      }

      const result = parse(data);

      if (result.err) {
        throw new Error(`JSON parsing failed: ${result.err.message}`);
      }

      return result.value;
    }
  ]
});

// Usage
apiClient.get('/data')
  .then(response => console.log(response.data))
  .catch(error => console.error(error));

Alternative Parsers

Depending on your application's requirements, other specialized parsers can be integrated using the same pattern.

Using destr for Fast and Safe Parsing

destr is a lightweight, drop-in replacement for JSON.parse that prevents prototype pollution and gracefully falls back to the original string if parsing fails.

npm install destr
import axios from 'axios';
import { destr } from 'destr';

const apiClient = axios.create({
  transformResponse: [
    (data) => (typeof data === 'string' ? destr(data) : data)
  ]
});

Using json-bigint for Large Number Support

When working with APIs that return 64-bit integer IDs (such as Twitter or database auto-increments), native parsing causes precision truncation.

npm install json-bigint
import axios from 'axios';
import JSONBig from 'json-bigint';

const JSONBigNative = JSONBig({ useNativeBigInt: true });

const apiClient = axios.create({
  transformResponse: [
    (data) => {
      if (typeof data !== 'string') {
        return data;
      }
      try {
        return JSONBigNative.parse(data);
      } catch (err) {
        return data;
      }
    }
  ]
});

Applying Parsers Globally vs. Per-Request

axios.defaults.transformResponse = [
  (data) => (typeof data === 'string' ? parse(data).value : data)
];
axios.get('/huge-payload', {
  transformResponse: [
    (data) => (typeof data === 'string' ? parse(data).value : data)
  ]
});