How to Serialize Complex Objects Using jQuery $.param()

Serializing complex JavaScript objects into URL-encoded query strings is a common requirement when sending data across HTTP GET requests or form submissions. This guide demonstrates how to use the jQuery $.param() method to serialize deeply nested objects, explains how jQuery formats nested keys using bracket notation, and highlights the crucial role of the traditional parameter.

Understanding $.param() Syntax

The jQuery.param() method accepts two arguments:

$.param( obj )
$.param( obj, traditional )
  • obj: An array or an object to serialize.
  • traditional: A boolean flag. When set to false (default), jQuery recursively serializes nested objects and arrays using bracket notation. When set to true, it performs shallow serialization.

Serializing a Deeply Nested Object

By default, $.param() handles deep structures automatically. It converts nested keys and arrays into a format compatible with back-end frameworks like PHP, Ruby on Rails, and ASP.NET.

Consider the following complex object containing strings, numbers, nested objects, and arrays:

const complexData = {
  user: {
    id: 101,
    name: "Jane Doe",
    contact: {
      email: "jane@example.com",
      phone: "555-0199"
    }
  },
  roles: ["admin", "editor"],
  preferences: {
    notifications: true,
    theme: "dark"
  }
};

const serializedString = $.param(complexData);
console.log(serializedString);

Output

The raw output is fully URL-encoded:

user%5Bid%5D=101&user%5Bname%5D=Jane+Doe&user%5Bcontact%5D%5Bemail%5D=jane%40example.com&user%5Bcontact%5D%5Bphone%5D=555-0199&roles%5B%5D=admin&roles%5B%5D=editor&preferences%5Bnotifications%5D=true&preferences%5Btheme%5D=dark

When decoded with decodeURIComponent(), the structure reveals how jQuery represents nesting:

user[id]=101&user[name]=Jane Doe&user[contact][email]=jane@example.com&user[contact][phone]=555-0199&roles[]=admin&roles[]=editor&preferences[notifications]=true&preferences[theme]=dark

The Role of the traditional Flag

When working with complex objects, avoid setting traditional: true. Setting this flag disables recursive serialization:

// Incorrect for complex objects
const shallow = $.param(complexData, true);

Under shallow serialization, nested objects are converted to [object+Object] strings, causing data loss:

user=%5Bobject+Object%5D&roles=admin&roles=editor&preferences=%5Bobject+Object%5D

Always rely on the default behavior (traditional: false) when your payload contains nested objects.

Handling Arrays of Objects

$.param() also preserves index hierarchy when dealing with arrays of objects:

const order = {
  orderId: 54321,
  items: [
    { sku: "A1", qty: 2 },
    { sku: "B2", qty: 5 }
  ]
};

console.log(decodeURIComponent($.param(order)));

Decoded Result:

orderId=54321&items[0][sku]=A1&items[0][qty]=2&items[1][sku]=B2&items[1][qty]=5

Each array element receives an explicit numerical index to keep the sub-properties associated with the correct object during back-end deserialization.