紀錄工作經驗、相關知識,解決技術相關問題。

HTML, Javascript, React, 網站相關

[JS] 將 Object 資料型態轉換為 GET 字串參數:URLSearchParams 與陣列空值處理

[JS] 將 Object 資料型態轉換為 GET 字串參數:URLSearchParams 與陣列空值處理 特色圖片

在前端串接 RESTful API 或處理頁面篩選導頁時,我們經常需要將搜尋條件從 JavaScript Object 資料型態轉換為 GET 字串參數(Query String,例如 i=abc&m=Some%20value)。過去常見用 Object.keys() 搭配字串拼接的做法,不僅程式碼冗長,還容易漏掉特殊字元的 URL 編碼。本篇整理使用原生 URLSearchParams 快速轉換的標準語法,以及實務上遇到 undefined、null 與陣列時的進階處理函式。

💡 反向解析需求:如果你的需求相反,是想把網址上的 ?a=1&b=2 轉回物件或讀取特定參數,請參考站內另一篇 JS 解析 URL:new URL 與 URLSearchParams 屬性對照。

一、基礎用法:使用 new URLSearchParams() 一行轉換

當資料物件的屬性值皆為單純的字串或數字時,直接將該 Object 傳入 new URLSearchParams(data) 並呼叫 .toString(),瀏覽器就會自動完成鍵值組裝與 URL 百分比編碼(Percent-encoding):

const data = {
  i: 'abc',
  m: 'Some value',
  page: 1,
};

// 直接將 Object 轉換為 GET 參數格式的字串
const params = new URLSearchParams(data).toString();

console.log(params);
// 輸出結果:
// "i=abc&m=Some+value&page=1"

ℹ️ 關於空白字元的編碼差異:依據 WHATWG application/x-www-form-urlencoded 規範,URLSearchParams.toString() 會將空白字元編碼為 +(例如 Some+value);若後端 API 嚴格要求空白必須編碼為 %20,可在結尾加上 .replace(/\+/g, '%20'),或改用下方第三節的 encodeURIComponent 寫法。

二、實務避坑:處理 Object 中的 undefined、null 與陣列

雖然直接把物件丟進 new URLSearchParams(data) 非常方便,但在真實專案的表單篩選中,物件經常包含未填寫的 undefined、null 或多選陣列。若未先過濾就直接轉換,會踩到以下兩個常見陷阱:

  1. undefined 與 null 會被轉成字面字串:{ keyword: undefined, tag: null } 會被轉成 "keyword=undefined&tag=null",導致後端誤以為使用者搜尋 "undefined" 這個關鍵字!
  2. 陣列會被強制合併為逗號字串:{ ids: [10, 20] } 會被轉成 "ids=10%2C20",而非多數後端框架預期的重複同名參數 ids=10&ids=20。

支援過濾空值與展開陣列的通用轉換函式

以下封裝一個可直接複製到專案工具庫(utils)的實務轉換函式,能自動剔除 undefined / null / 空字串,並將陣列正確展開為多筆同名參數:

/**
 * 將 JavaScript Object 安全轉換為 GET 查詢字串參數
 * @param {Record<string, any>} obj 原始參數物件
 * @returns {string} 編碼後的 Query String(不含開頭問號)
 */
function objectToGetParams(obj) {
  const searchParams = new URLSearchParams();

  Object.entries(obj || {}).forEach(([key, value]) => {
    // 1. 自動忽略 undefined、null 與空字串
    if (value === undefined || value === null || value === '') {
      return;
    }

    // 2. 若屬性值為陣列,逐一使用 append 加入同名參數 (例如 ids=10&ids=20)
    if (Array.isArray(value)) {
      value.forEach((item) => {
        if (item !== undefined && item !== null) {
          searchParams.append(key, String(item));
        }
      });
      return;
    }

    // 3. 一般基本型別(字串、數字、布林值)
    searchParams.append(key, String(value));
  });

  return searchParams.toString();
}

// 測試範例
const filterCriteria = {
  i: 'abc',
  m: 'Some value',
  emptyField: undefined,
  nullField: null,
  tags: ['js', 'react'],
};

console.log(objectToGetParams(filterCriteria));
// 輸出結果:
// "i=abc&m=Some+value&tags=js&tags=react"

三、需要將空白轉為 %20 時:Object.entries + encodeURIComponent

如果你的後端簽章驗證或第三方 API 要求空白字元必須編碼為 %20(標準 RFC 3986 格式)而非 +,可以使用 Object.entries() 搭配 encodeURIComponent():

function objectToRfc3986Query(obj) {
  return Object.entries(obj || {})
    .filter(([, value]) => value !== undefined && value !== null && value !== '')
    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
    .join('&');
}

const data = {
  i: 'abc',
  m: 'Some value',
};

console.log(objectToRfc3986Query(data));
// 輸出結果:
// "i=abc&m=Some%20value"

四、三種 Object 轉 GET 參數寫法對照表

轉換寫法空白字元編碼undefined / null 處理適用情境
new URLSearchParams(obj).toString()轉為 +轉成 "undefined" 字串(需注意)屬性值皆為已知純字串/數字的簡單物件
自訂 objectToGetParams(obj) 迴圈 append轉為 +自動剔除空值並支援陣列展開實務專案的搜尋篩選器、API 查詢參陣列裝
Object.entries + encodeURIComponent轉為 %20透過 .filter() 預先剔除嚴格要求 %20 編碼的第三方 API 或簽章計算

💡 延伸閱讀:完成 GET 參數轉換後,若要在 jQuery 或 Next.js 中發送請求與同步網址,可參考 jQuery ajax POST / GET 使用範例 以及 [前端筆記] Next.js URL 更新不刷新網頁。

參考資料與延伸閱讀