- Spec files
npm-axios
Describes: pkg:npm/axios@1.11.x
- Description
- Promise based HTTP client for the browser and node.js
- Author
- tessl
- Last updated
data-transformation.md docs/
1# Data Transformation23Convert between different data formats including FormData, JSON, and URL-encoded data with extensive serialization options, configuration merging, and adapter selection.45## Capabilities67### Form Data Conversion89Convert JavaScript objects to FormData with advanced serialization options for file uploads and form submissions.1011```javascript { .api }12/**13* Convert object to FormData with serialization options14* @param sourceObj - Object to convert to FormData15* @param targetFormData - Existing FormData to append to (optional)16* @param options - Serialization configuration options17* @returns FormData instance with serialized object data18*/19axios.toFormData(20sourceObj: object,21targetFormData?: GenericFormData,22options?: FormSerializerOptions23): GenericFormData;2425interface FormSerializerOptions extends SerializerOptions {26/** Custom visitor function for object traversal */27visitor?: SerializerVisitor;28/** Use dot notation for nested objects */29dots?: boolean;30/** Include meta tokens in keys */31metaTokens?: boolean;32/** Use array indexes in keys */33indexes?: boolean | null;34}3536interface SerializerVisitor {37(38this: GenericFormData,39value: any,40key: string | number,41path: null | Array<string | number>,42helpers: FormDataVisitorHelpers43): boolean;44}4546interface GenericFormData {47append(name: string, value: any, options?: any): any;48}49```5051**Usage Examples:**5253```javascript54import axios from "axios";5556// Basic object to FormData conversion57const userData = {58name: "John Doe",59email: "john@example.com",60age: 30,61avatar: fileInput.files[0] // File object62};6364const formData = axios.toFormData(userData);6566// Send as multipart/form-data67await axios.post("/api/users", formData, {68headers: { "Content-Type": "multipart/form-data" }69});7071// Nested object conversion with dots notation72const complexData = {73user: {74profile: {75name: "Alice",76settings: {77theme: "dark",78notifications: true79}80}81},82files: [file1, file2]83};8485const formDataWithDots = axios.toFormData(complexData, undefined, {86dots: true,87indexes: true88});8990// Results in FormData with keys like:91// user.profile.name = "Alice"92// user.profile.settings.theme = "dark"93// files[0] = file194// files[1] = file29596// Custom visitor for advanced serialization97const customFormData = axios.toFormData(data, undefined, {98visitor: function(value, key, path, helpers) {99if (value instanceof Date) {100this.append(key, value.toISOString());101return false; // Don't continue default processing102}103104if (typeof value === "boolean") {105this.append(key, value ? "1" : "0");106return false;107}108109return helpers.defaultVisitor.call(this, value, key, path, helpers);110}111});112```113114### JSON to Form Data Conversion115116Convert FormData or HTML form elements back to JSON objects.117118```javascript { .api }119/**120* Convert FormData or HTMLFormElement to JSON object121* @param form - FormData instance or HTML form element122* @returns Plain JavaScript object with form data123*/124axios.formToJSON(form: GenericFormData | GenericHTMLFormElement): object;125126interface GenericHTMLFormElement {127name: string;128method: string;129submit(): void;130}131```132133**Usage Examples:**134135```javascript136// Convert FormData to JSON137const formData = new FormData();138formData.append("name", "John");139formData.append("email", "john@example.com");140formData.append("age", "30");141142const jsonData = axios.formToJSON(formData);143console.log(jsonData); // { name: "John", email: "john@example.com", age: "30" }144145// Convert HTML form to JSON146const formElement = document.getElementById("user-form");147const formJson = axios.formToJSON(formElement);148149// Use in request150await axios.post("/api/users", formJson);151152// Handle complex form structures153const complexForm = new FormData();154complexForm.append("user[name]", "Alice");155complexForm.append("user[email]", "alice@example.com");156complexForm.append("preferences[theme]", "dark");157complexForm.append("tags[]", "admin");158complexForm.append("tags[]", "user");159160const parsedData = axios.formToJSON(complexForm);161// Results in nested object structure based on form field names162```163164### Configuration Merging165166Merge multiple axios configurations with intelligent precedence handling.167168```javascript { .api }169/**170* Merge two axios configurations intelligently171* @param config1 - Base configuration172* @param config2 - Override configuration173* @returns Merged configuration with proper precedence174*/175axios.mergeConfig<D = any>(176config1: AxiosRequestConfig<D>,177config2: AxiosRequestConfig<D>178): AxiosRequestConfig<D>;179```180181**Usage Examples:**182183```javascript184// Base configuration185const baseConfig = {186baseURL: "https://api.example.com",187timeout: 5000,188headers: {189"Accept": "application/json",190"User-Agent": "MyApp/1.0"191},192params: {193version: "v1"194}195};196197// Override configuration198const requestConfig = {199timeout: 10000, // Override timeout200headers: {201"Authorization": "Bearer token123", // Add new header202"Accept": "application/json, text/plain" // Override accept203},204params: {205limit: 10 // Add new parameter206}207};208209const merged = axios.mergeConfig(baseConfig, requestConfig);210console.log(merged);211/* Result:212{213baseURL: "https://api.example.com",214timeout: 10000, // Overridden215headers: {216"Accept": "application/json, text/plain", // Overridden217"User-Agent": "MyApp/1.0", // Preserved218"Authorization": "Bearer token123" // Added219},220params: {221version: "v1", // Preserved222limit: 10 // Added223}224}225*/226227// Use in instance creation228const apiClient = axios.create(baseConfig);229230// Merge for specific requests231const response = await apiClient.request(232axios.mergeConfig(requestConfig, {233method: "get",234url: "/users"235})236);237```238239### Adapter Selection240241Select appropriate request adapter based on environment and requirements.242243```javascript { .api }244/**245* Get appropriate adapter from configuration246* @param adapters - Adapter configuration (string, function, or array)247* @returns Resolved adapter function248*/249axios.getAdapter(adapters: AxiosAdapterConfig | AxiosAdapterConfig[] | undefined): AxiosAdapter;250251type AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName;252type AxiosAdapterName = 'fetch' | 'xhr' | 'http' | (string & {});253254interface AxiosAdapter {255(config: InternalAxiosRequestConfig): AxiosPromise;256}257```258259**Usage Examples:**260261```javascript262// Get default adapter263const defaultAdapter = axios.getAdapter();264265// Specify preferred adapters in order266const adapter = axios.getAdapter(['fetch', 'xhr', 'http']);267268// Use specific adapter269const fetchAdapter = axios.getAdapter('fetch');270const xhrAdapter = axios.getAdapter('xhr');271const httpAdapter = axios.getAdapter('http'); // Node.js only272273// Use in configuration274const config = {275url: "/api/data",276adapter: axios.getAdapter(['fetch', 'xhr'])277};278279// Custom adapter selection logic280function selectAdapter(environment) {281if (environment === 'node') {282return axios.getAdapter('http');283} else if (typeof fetch !== 'undefined') {284return axios.getAdapter('fetch');285} else {286return axios.getAdapter('xhr');287}288}289290const customAdapter = selectAdapter(process.env.NODE_ENV);291```292293### URL Parameter Serialization294295Advanced URL parameter serialization with custom encoders and formats.296297```javascript { .api }298interface ParamsSerializerOptions extends SerializerOptions {299/** Custom parameter encoder function */300encode?: ParamEncoder;301/** Custom serialization function */302serialize?: CustomParamsSerializer;303}304305interface ParamEncoder {306(value: any, defaultEncoder: (value: any) => any): any;307}308309interface CustomParamsSerializer {310(params: Record<string, any>, options?: ParamsSerializerOptions): string;311}312```313314**Usage Examples:**315316```javascript317// Custom parameter serialization318const config = {319url: "/api/search",320params: {321query: "hello world",322filters: {323category: "tech",324date: new Date("2023-01-01")325},326tags: ["javascript", "api"]327},328paramsSerializer: {329serialize: (params, options) => {330const searchParams = new URLSearchParams();331332Object.entries(params).forEach(([key, value]) => {333if (Array.isArray(value)) {334value.forEach(item => searchParams.append(`${key}[]`, item));335} else if (typeof value === "object" && value !== null) {336Object.entries(value).forEach(([nestedKey, nestedValue]) => {337searchParams.append(`${key}[${nestedKey}]`, nestedValue);338});339} else {340searchParams.append(key, value);341}342});343344return searchParams.toString();345}346}347};348349// Results in URL: /api/search?query=hello+world&filters[category]=tech&filters[date]=2023-01-01T00:00:00.000Z&tags[]=javascript&tags[]=api350351// Custom encoder for special characters352const customEncoderConfig = {353params: { special: "hello+world" },354paramsSerializer: {355encode: (value, defaultEncoder) => {356if (typeof value === "string") {357return encodeURIComponent(value).replace(/%20/g, "+");358}359return defaultEncoder(value);360}361}362};363```364365### Request and Response Transformers366367Transform request and response data automatically.368369```javascript { .api }370interface AxiosRequestTransformer {371(this: InternalAxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any;372}373374interface AxiosResponseTransformer {375(this: InternalAxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number): any;376}377```378379**Usage Examples:**380381```javascript382// Custom request transformer383const requestTransformer = function(data, headers) {384if (data && typeof data === "object") {385// Convert camelCase to snake_case for API386const transformed = {};387Object.entries(data).forEach(([key, value]) => {388const snakeKey = key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);389transformed[snakeKey] = value;390});391return JSON.stringify(transformed);392}393return data;394};395396// Custom response transformer397const responseTransformer = function(data, headers, status) {398if (typeof data === "string") {399try {400data = JSON.parse(data);401} catch (e) {402return data;403}404}405406if (data && typeof data === "object") {407// Convert snake_case to camelCase408const transformed = {};409Object.entries(data).forEach(([key, value]) => {410const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());411transformed[camelKey] = value;412});413return transformed;414}415416return data;417};418419// Use transformers in configuration420const apiClient = axios.create({421transformRequest: [requestTransformer, ...axios.defaults.transformRequest],422transformResponse: [...axios.defaults.transformResponse, responseTransformer]423});424425// Multiple transformers426const multiTransformConfig = {427transformRequest: [428// First transformer: handle dates429(data, headers) => {430if (data && typeof data === "object") {431Object.entries(data).forEach(([key, value]) => {432if (value instanceof Date) {433data[key] = value.toISOString();434}435});436}437return data;438},439// Second transformer: JSON stringify440(data, headers) => {441if (data && typeof data === "object") {442headers.setContentType("application/json");443return JSON.stringify(data);444}445return data;446}447]448};449```450451### Advanced Configuration Examples452453Real-world examples of complex data transformation and configuration scenarios.454455**Usage Examples:**456457```javascript458// Complex file upload with progress and validation459const uploadFile = async (file, metadata) => {460const formData = axios.toFormData({461file: file,462metadata: JSON.stringify(metadata),463timestamp: new Date().toISOString()464}, undefined, {465dots: true,466indexes: true,467visitor: function(value, key, path, helpers) {468// Custom handling for different data types469if (value instanceof Date) {470this.append(key, value.toISOString());471return false; // Don't use default handling472}473if (typeof value === 'object' && value.constructor.name === 'File') {474this.append(key, value, value.name);475return false;476}477// Use default handling for other types478return true;479}480});481482return axios.post('/api/upload', formData, {483headers: { 'Content-Type': 'multipart/form-data' },484onUploadProgress: (progressEvent) => {485const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);486console.log(`Upload progress: ${percentCompleted}%`);487},488timeout: 30000, // 30 second timeout for file uploads489maxBodyLength: 50 * 1024 * 1024 // 50MB max file size490});491};492493// API client with automatic data transformation494const createAPIClient = (baseURL) => {495const client = axios.create({ baseURL });496497// Transform snake_case API responses to camelCase498client.defaults.transformResponse = [499...client.defaults.transformResponse,500(data) => {501if (typeof data === 'object' && data !== null) {502return transformKeys(data, camelCase);503}504return data;505}506];507508// Transform camelCase requests to snake_case509client.defaults.transformRequest = [510(data) => {511if (typeof data === 'object' && data !== null) {512return transformKeys(data, snakeCase);513}514return data;515},516...client.defaults.transformRequest517];518519return client;520};521522// Helper function for key transformation523function transformKeys(obj, transformer) {524if (Array.isArray(obj)) {525return obj.map(item => transformKeys(item, transformer));526}527if (obj && typeof obj === 'object') {528return Object.keys(obj).reduce((result, key) => {529const transformedKey = transformer(key);530result[transformedKey] = transformKeys(obj[key], transformer);531return result;532}, {});533}534return obj;535}536537// Modern approach (preferred)538const responses = await Promise.all([539axios.get("/api/users"),540axios.get("/api/posts")541]);542543const [usersResponse, postsResponse] = responses;544545// Legacy all usage (use Promise.all instead)546axios.all([547axios.get("/api/users"),548axios.get("/api/posts")549]).then(axios.spread((usersRes, postsRes) => {550console.log("Users:", usersRes.data);551console.log("Posts:", postsRes.data);552}));553554// Modern approach (preferred)555Promise.all([556axios.get("/api/users"),557axios.get("/api/posts")558]).then(([usersRes, postsRes]) => {559console.log("Users:", usersRes.data);560console.log("Posts:", postsRes.data);561});562```563564### Advanced Data Transformation Patterns565566Complex transformation patterns for real-world applications.567568**Usage Examples:**569570```javascript571// Data normalization pipeline572class DataNormalizer {573static request(data) {574return Object.entries(data || {}).reduce((acc, [key, value]) => {575// Convert dates to ISO strings576if (value instanceof Date) {577acc[key] = value.toISOString();578}579// Convert boolean to string for some APIs580else if (typeof value === "boolean") {581acc[key] = value.toString();582}583// Convert camelCase to snake_case584else {585const snakeKey = key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);586acc[snakeKey] = value;587}588return acc;589}, {});590}591592static response(data) {593if (!data || typeof data !== "object") return data;594595return Object.entries(data).reduce((acc, [key, value]) => {596// Convert snake_case to camelCase597const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());598599// Parse ISO date strings back to Date objects600if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value)) {601acc[camelKey] = new Date(value);602} else {603acc[camelKey] = value;604}605606return acc;607}, {});608}609}610611// Use in axios configuration612const normalizedClient = axios.create({613transformRequest: [614DataNormalizer.request,615...axios.defaults.transformRequest616],617transformResponse: [618...axios.defaults.transformResponse,619DataNormalizer.response620]621});622623// Conditional transformation based on content type624const smartTransformer = function(data, headers) {625const contentType = headers.getContentType();626627if (contentType === "application/json") {628return JSON.stringify(data);629} else if (contentType === "application/x-www-form-urlencoded") {630return new URLSearchParams(data).toString();631} else if (contentType === "multipart/form-data") {632return axios.toFormData(data);633}634635return data;636};637```