JSON to Excel Tool Implementation: From Data Transformation to Browser-Side File Generation#

Written: May 7, 2026 at 21:14

As a frontend developer, data export requirements come up frequently. Users want to export JSON data returned from APIs into Excel. The product manager says “just add a button.” Sounds simple, but when you actually implement it, you need to consider encoding issues, data type handling, and file format compatibility. Let’s talk about how JsonKit’s JSON to Excel tool works under the hood.

Core Approach: A Lightweight Solution Without Third-Party Libraries#

There are many Excel libraries out there, like SheetJS and ExcelJS. They’re powerful but also quite heavy. If your requirement is simply “export JSON data into a file that Excel can open,” there’s actually a lightweight alternative: generate CSV/TSV format and let Excel parse it.

Why TSV Instead of CSV?#

CSV (comma-separated) has a classic problem: what if the data itself contains commas?

// This row will break Excel's parsing
const row = { name: "John,Jane", age: 25 }
// CSV: John,Jane,25  ← Excel splits this into three columns

TSV (Tab-separated) is much more stable because Tab characters rarely appear in data:

// TSV format
const tsv = 'name\tage\nJohn,Jane\t25'
// Excel correctly parses as two columns

Data Structure Transformation: Flattening and Nested Handling#

Converting JSON to Excel is essentially flattening a tree structure. Let’s look at the core transformation logic:

function jsonToExcel(data) {
  // Normalize: wrap single object into array
  let rows = Array.isArray(data) ? data : [data]

  // Extract all possible column names (deduplicated)
  const columns = Array.from(new Set(
    rows.flatMap(Object.keys)
  ))
  // Result example: ['name', 'age', 'city', 'email']

  // Generate header row
  let tsv = columns.join('\t') + '\n'

  // Process each row
  rows.forEach(row => {
    const values = columns.map(col => {
      const val = row[col]
      if (val === null || val === undefined) return ''
      if (typeof val === 'object') return JSON.stringify(val)
      return String(val).replace(/\t/g, ' ').replace(/\n/g, ' ')
    })
    tsv += values.join('\t') + '\n'
  })

  return tsv
}

Several details are worth noting:

1. Smart Column Name Extraction#

flatMap(Object.keys) combined with Set deduplication automatically handles cases where “different objects have different fields”:

const data = [
  { name: 'John', age: 25 },
  { name: 'Jane', city: 'New York' },  // no age, has city
  { name: 'Bob', age: 30, email: 'bob@example.com' }
]
// Extracted columns: ['name', 'age', 'city', 'email']
// Missing fields are automatically left empty

2. Handling Nested Objects#

What about nested objects? Simply JSON.stringify them:

const row = {
  name: 'John',
  address: { city: 'New York', district: 'Manhattan' }
}
// Excel cell displays: {"city":"New York","district":"Manhattan"}

This is more practical than recursively flattening—users can process it further with Excel formulas.

The Ultimate Solution for Encoding Issues: BOM#

Chinese characters in Excel exports—every developer’s nightmare. The solution is simple and brutal: add a BOM (Byte Order Mark) at the beginning of the file.

// UTF-8 BOM
const BOM = '\uFEFF'
const tsv = BOM + columns.join('\t') + '\n' + rowsData

// Specify MIME type when creating Blob
const blob = new Blob([tsv], {
  type: 'application/vnd.ms-excel;charset=utf-8'
})

\uFEFF is the UTF-8 BOM marker. When Excel sees it, it knows “this file is UTF-8 encoded,” and Chinese characters display correctly.

File Download: Blob API and Memory Management#

Frontend file generation离不开 Blob API. The complete download workflow:

function downloadExcel(tsvContent, fileName) {
  // Create Blob
  const blob = new Blob([tsvContent], {
    type: 'application/vnd.ms-excel;charset=utf-8'
  })

  // Create temporary URL
  const url = URL.createObjectURL(blob)

  // Trigger download
  const a = document.createElement('a')
  a.href = url
  a.download = `${fileName}.xls`
  document.body.appendChild(a)
  a.click()

  // Clean up memory
  document.body.removeChild(a)
  URL.revokeObjectURL(url)  // Important! Free memory
}

URL.revokeObjectURL is easily overlooked but crucial for memory management. Every createObjectURL keeps file data in memory. Without releasing it, frequent exports of large files will cause memory leaks.

Real-World Use Cases#

This tool is perfect for:

  1. API Data Export: Backend returns JSON, frontend gives users a download
  2. Form Data Summary: Users filled out multiple forms, export to Excel with one click
  3. Data Migration: Export old system’s JSON configurations to spreadsheets for operations teams to edit

Performance Boundaries and Optimization#

Are there limits to pure frontend processing? Absolutely:

  • Large File Handling: JSON over 10MB will cause lag with string concatenation
  • Solution: Switch to streaming (TextEncoder + WritableStream)

But for most scenarios (a few thousand rows), this lightweight solution is more than sufficient, and the code is under 50 lines.


If you also need to implement JSON to Excel conversion in your frontend, try JsonKit JSON to Excel Tool—no libraries needed, get it done right in the browser. Also check out JSON to CSV Tool for pure data export scenarios. There’s also a JSON Online Viewer to help you organize your data structure before exporting.