← All posts
WindowsPublished · 8 min read

How to convert JSON to CSV on Windows without installing anything — PowerShell, Python and Excel, and why your leading zeros disappear

You usually convert JSON to CSV to look at an API response or an export in Excel. Most search results are converter sites, but Windows PowerShell or Python's standard library do it locally. Follow the common one-liner, though, and you get columns named Count and Length, ??? instead of text, cells reading @{city=…}, missing columns, and zeros that vanish in Excel. Here each trap is reproduced with a three-record JSON file and fixed.

JSON formatter — Actual screen
Actual screen
Free tool featured in this guide
JSON formatter

Use it before converting to make sure the JSON is not broken. Paste it in to format it; if something is wrong it points to the line and column. Everything runs in your browser, so the data never leaves your PC.

  • ✓ Free
  • ✓ No install, no sign-up
  • ✓ Runs in your browser
  • ✓ Files are never uploaded

🔒 Your file is never sent to a server or anywhere else — it is processed only in your own browser.

Link goes to — a page on this same site (coding-now.com)
🔒 https://www.coding-now.com/en/json-formatter

Where JSON and CSV do not fit

A CSV is a flat table: column names on the first line and one value per column on every line below, with the same columns on every line. JSON can nest objects and arrays inside values, and each item may have different keys. Converting JSON to CSV therefore means deciding two things: how to spread nested values across columns, and how to collect keys that only some items have.

The test file holds three fake members. It has Korean names (to show what happens to non-English text), a phone number and postal code that start with 0 (01012345678, 04524), a join date as text, a memo with a comma, quotes and a line break, a nested address object (city, district) and a tags array. email exists only on the second record and a 16-digit order_no only on the third. It is saved as UTF-8 without a BOM, like most API responses (926 bytes).

json
[
  {
    "id": 1,
    "name": "김민준",
    "phone": "01012345678",
    "zip": "04524",
    "joined": "2026-10-19",
    "score": 88.5,
    "memo": "첫 주문, \"VIP\"",
    "address": { "city": "서울", "district": "중구" },
    "tags": ["신규", "쿠폰"]
  },
  { "id": 2, "name": "Lee, Seoyeon", "email": "lee@example.com", "…": "…" },
  { "id": 3, "name": "박지호", "order_no": "2026101900000123", "…": "…" }
]

Test machine: Windows 11, Windows PowerShell 5.1.26100, Python 3.11.9, Excel 16.0 (build 20430). Every conversion ran locally; nothing was uploaded.

Method 1: PowerShell, already on Windows

Open Windows PowerShell from Start (no admin rights needed). First list every key in the JSON. If you pick columns from the first item alone, you miss keys that only later items have.

Step 1: list the keys of all items

powershell
$src = "C:\Users\you\Downloads\data.json"   # the JSON file (full path)
$rows = Get-Content $src -Raw -Encoding UTF8 | ConvertFrom-Json
($rows | ForEach-Object { $_.PSObject.Properties.Name } | Select-Object -Unique) -join ','

The test file gave id,name,phone,zip,joined,score,memo,address,tags,email,order_no — 11 keys. The first item has only 9 of them.

Step 2: pick the columns and save the CSV

powershell
$src = "C:\Users\you\Downloads\data.json"   # the JSON file (full path)
$out = "C:\Users\you\Downloads\data.csv"    # the CSV to create (full path)

$rows = Get-Content $src -Raw -Encoding UTF8 | ConvertFrom-Json
$rows | Select-Object id, name, phone, zip, joined, score, memo,
  @{ n = 'city';     e = { $_.address.city } },       # pull out of the nested object
  @{ n = 'district'; e = { $_.address.district } },
  @{ n = 'tags';     e = { $_.tags -join ';' } },      # join arrays with ;
  email, order_no |                                    # list keys the first item lacks
  Export-Csv $out -NoTypeInformation -Encoding UTF8
  1. 1Change the $src and $out paths to your files. Full paths are safest.
  2. 2Replace the column names after Select-Object with the keys from step 1. Pull nested values out with @{ n = 'new column'; e = { $_.outer.inner } }.
  3. 3Paste the whole block and press Enter. It finishes silently and the CSV appears at $out.

The result was 456 bytes, starting with EF BB BF (a BOM), with 12 columns (id … city, district, tags, email, order_no); the second member's email and the third member's order_no landed in the right places. Values with commas were quoted ("Lee, Seoyeon") and quotes inside values were doubled (""VIP"").

⚠️

If you save the code as a .ps1 file, save it as UTF-8 with BOM. Windows PowerShell 5.1 reads a .ps1 without a BOM in the ANSI code page, which garbles non-English comments and paths (measured on this PC: the line after a Korean comment did not run). Pasting into the window is fine.

If the JSON is wrapped like { "items": [ … ] }, take the list out first with $rows = (Get-Content $src -Raw -Encoding UTF8 | ConvertFrom-Json).items and continue the same way (tested: both items came out).

Six traps reproduced in PowerShell

This is what happens when you run the one-liners found in search results, reproduced with the same test file.

What was runResult (measured)
Get-Content … | ConvertFrom-Json | Export-Csv in one pipeline8 columns: Count, Length, LongLength, Rank, SyncRoot … values 3, 3, 3, 1, System.Object[] (154 bytes) — no member data
Export-Csv without -EncodingAll Korean text became ??? (394 bytes)
Get-Content without -EncodingText read garbled, then ConvertFrom-Json stopped with an invalid-object error at position 497 (: or } expected; Windows showed it in Korean)
No -NoTypeInformationFirst line: #TYPE System.Management.Automation.PSCustomObject
Nested object and array left as isaddress cell: @{city=…; district=…}, tags cell: System.Object[]
Items with different keysNo email or order_no column at all — no error, no warning

The first row happens because ConvertFrom-Json in Windows PowerShell 5.1 sends the JSON array down the pipeline as one object. Export-Csv receives one array instead of three members and writes the array's own properties (Count, Length…) as columns. Storing the result in a variable or wrapping it in parentheses unrolls the array into one line per member.

The rest is spelled out in Microsoft's Export-Csv documentation for 5.1. The default -Encoding is ASCII, and the #TYPE header is the default before PowerShell 6.0. The columns come from the properties of the first object, and extra properties on later objects are not included — which is why email and order_no vanished silently.

Nested object and array: passed as is vs pulled out (measured)

Method 2: Python with the standard csv module

With Python installed you need nothing from pip: the standard json and csv modules are enough. The code below spreads nested objects into dotted columns such as address.city, joins arrays with semicolons, and builds the column list from every item.

python
import csv, json

def flatten(obj, prefix=""):
    out = {}
    for k, v in obj.items():
        key = prefix + k
        if isinstance(v, dict):                     # {"address": {"city": …}} -> address.city
            out.update(flatten(v, key + "."))
        elif isinstance(v, list):                   # ["a", "b"] -> a;b
            out[key] = ";".join(str(x) for x in v)
        else:
            out[key] = v
    return out

with open("data.json", encoding="utf-8") as f:
    rows = [flatten(r) for r in json.load(f)]

keys = []                                           # collect keys from every item, not just the first
for r in rows:
    for k in r:
        if k not in keys:
            keys.append(k)

with open("data.csv", "w", encoding="utf-8-sig", newline="") as f:   # BOM + newline=""
    w = csv.DictWriter(f, fieldnames=keys)
    w.writeheader()
    w.writerows(rows)

Run it in the folder with data.json and you get a 392-byte CSV (with BOM, 12 columns). Numbers stay numbers; null values and missing keys become empty cells.

  • fieldnames from the first item stops the script. fieldnames=data[0].keys() ended with ValueError: dict contains fields not in fieldnames: 'email'. As the Python docs say, DictWriter raises ValueError for unknown keys by default (extrasaction='raise').
  • Without newline="" you get blank rows. Lines were saved ending in \r\r\n (4 places), and Excel opened the 4-line table as 7 lines with a blank row between members. The Python docs warn that without newline='' an extra \r is added on Windows.
  • encoding="utf-8" alone garbles text in Excel. The file is fine, but it has no BOM (next section). For Excel use utf-8-sig.
  • Without flattening, cells contain Python-looking text such as {'city': …, 'district': …} and ['…', '…'].

Opening the CSV in Excel: garbled text and missing zeros

Microsoft's support article says a UTF-8 CSV opens normally in Excel only if it was saved with a BOM. Opened without one, the Korean names were garbled — and worse, the garbled bytes swallowed a comma, so on the third line the name and phone number ended up in one cell and every later cell shifted left. The shifted columns are easier to miss than the garbled text.

Even with a BOM and readable text, Excel turns anything that looks like a number into a number. The CSV file still contains 01012345678; Excel changes it while opening.

Values changed when the CSV was opened in Excel (measured)
ColumnJSON valueCSV opened in ExcelJSON read with Power Query
phone"01012345678"1012345678 (shown as 1.01E+09)01012345678 (text)
zip"04524"452404524 (text)
order_no"2026101900000123"2026101900000120 (shown as 2.03E+15)2026101900000123 (text)
joined"2026-10-19"Date value (#### if the column is narrow)2026-10-19 (text)

Microsoft's article on keeping leading zeros and large numbers explains that Excel removes leading zeros automatically and has a precision of 15 significant digits, so digits from the 16th on become 0. Changing the cell format to Text afterwards does not bring them back, so prevent it before opening. One of the article's suggestions is setting the column type to Text in Power Query.

Method 3: import the JSON directly with Power Query (if Excel is the goal)

If you will end up looking at the data in Excel, skip CSV. Power Query, built into Excel, reads JSON directly (Microsoft Learn's JSON connector page lists Excel among the supported products).

  1. 1In Excel choose Data > Get Data > From File > From JSON (menu names per Microsoft's support article; they may differ slightly by version).
  2. 2Pick the JSON file; the Power Query editor opens.
  3. 3For nested columns such as address, use the expand button in the column header to choose the inner keys.
  4. 4Check that columns where zeros matter, such as phone numbers, are typed as Text, then Close & Load.

Reading the test file with the same engine (Json.Document) and loading it into a sheet kept 01012345678, 04524, 2026101900000123 and 2026-10-19 as text, because quoted JSON values arrive as text. Nested values showed as Record and List until expanded. The editor screen itself was not checked for this guide.

If you then need a CSV, use Save As > CSV UTF-8 (Comma delimited). In the test it produced 392 bytes with a BOM, the same size as the Python output, and the zeros were intact in the file. But opening that CSV in Excel again stripped the zeros again — hand the CSV to the program that needs it, and keep the workbook for looking at the data in Excel.

Comparison

MethodInstallNon-English textNested valuesKeys missing from item 1Leading zeros in Excel
PowerShell one-liner (common in search results)None??? (ASCII default)@{…}, System.Object[]DroppedLost
PowerShell (code in this guide)NoneOK (BOM)Pulled into columnsKept if you list themLost when the CSV is opened
Python standard csv (code in this guide)PythonOK (utf-8-sig)Flattened to address.cityCollected automaticallyLost when the CSV is opened
Excel Power QueryNone (Excel)OKExpand button—Kept (text)

When the result looks wrong: check in this order

JSON to CSV went wrong — check from the top
  1. 1Columns named Count, Length… — the array went through as one object. Store the result in a variable or wrap it in ( ) before Export-Csv.
  2. 2??? or garbled text — ??? means the write encoding was missing; garbled text or a JSON error means the read encoding was missing. Garbled only in Excel means there is no BOM.
  3. 3Cells with @{…}, System.Object[] or {'city': …} — nested objects and arrays were not flattened. Pull fields out as in the code above.
  4. 4Missing columns, or zeros gone in Excel — columns came from the first item, or Excel converted text to numbers. List the keys first, and use Power Query for Excel.

If the JSON itself is broken, ConvertFrom-Json or json.load stops right away. Paste it into the JSON formatter to see the line and column that is wrong.

FAQ

Q. Excel drops the leading zero of phone numbers in my CSV. Is the file wrong?

No. The tested CSV still contained 01012345678; Excel turned it into the number 1012345678 while opening. If you are going to view it in Excel, import the JSON with Data > Get Data > From JSON instead — in the test the zeros stayed.

Q. Do commas, quotes or line breaks in values break the columns?

All three methods quoted such values. "Lee, Seoyeon" stayed in one cell, quotes inside the memo were doubled, and the memo with a line break opened as a single cell in Excel.

Q. Why does the one-liner output only Count and Length?

ConvertFrom-Json in Windows PowerShell 5.1 passes the array on as one object (measured on this PC). Store the result in a variable or wrap it in parentheses and you get one line per item.

Q. Is it the same in PowerShell 7?

Per Microsoft's docs, the #TYPE header is no longer the default from 6.0. PowerShell 7 is not installed on this PC, so the other behaviors were not tested.

Q. Can I use an online converter?

Online converters were not tested here. For member data or company API responses that should not leave your PC, the three local methods in this guide are the safer choice.

Free tool featured in this guide
JSON formatter

Use it before converting to make sure the JSON is not broken. Paste it in to format it; if something is wrong it points to the line and column. Everything runs in your browser, so the data never leaves your PC.

  • ✓ Free
  • ✓ No install, no sign-up
  • ✓ Runs in your browser
  • ✓ Files are never uploaded

🔒 Your file is never sent to a server or anywhere else — it is processed only in your own browser.

Link goes to — a page on this same site (coding-now.com)
🔒 https://www.coding-now.com/en/json-formatter

Comments 0

No comments yet. Be the first.

Only members can comment.

Comments with ads, abuse, personal information or illegal content are hidden or removed. Comments are shown with your nickname. Privacy Policy

More posts