How to convert a mongodb json export to csv
- Step 1Produce the export — Run
mongoexport --db mydb --collection users --out users.jsonfor NDJSON, or add--jsonArrayfor a single JSON array. Both formats work here. Drop the resulting file onto the converter above (free files cap at 2 MB). - Step 2Set the input format — Leave Auto detect on — it parses the file as JSON first and falls back to NDJSON automatically, which covers the default
mongoexportNDJSON output. Force NDJSON / JSONL if you want to be explicit. - Step 3Keep Flatten nested objects on — Embedded documents then become dot-notation columns. This also flattens Extended-JSON wrappers, so
_idbecomes_id.$oidand dates become<field>.$date— the raw values, not a friendlier form. - Step 4Optionally pre-process the `$oid` / `$date` wrappers — If you want a clean
_idcolumn instead of_id.$oid, rename or restructure those keys first with json-key-renamer, then convert. The converter itself does not strip Extended-JSON wrappers. - Step 5Choose array handling and delimiter — Pick JSON / Pipe / Comma for embedded array fields and Comma / Semicolon / Tab for the delimiter, depending on how the analyst will open the file.
- Step 6Convert and download — Click Convert to CSV, verify the Records-in count matches your document count, then download Excel-Ready CSV (BOM + CRLF) for spreadsheets or plain CSV for code.
How mongoexport shapes convert
What happens to common MongoDB document structures. The converter is faithful to Extended JSON — it flattens wrappers rather than interpreting them.
| Mongo field | Extended JSON | CSV column → value |
|---|---|---|
ObjectId _id | {"_id": {"$oid": "6627..."}} | _id.$oid → 6627... (raw hex, not unwrapped) |
| Date field | {"created": {"$date": "2026-01-02T..."}} | created.$date → the ISO string |
| Embedded document | {"address": {"city": "NYC"}} | address.city → NYC |
| Embedded array | {"tags": ["a", "b"]} | tags → one cell, per Array values setting |
| Missing field | absent in this document | Empty cell under the union header |
Export modes and matching input format
Choose the input format that matches how you ran mongoexport.
| mongoexport command | File shape | Recommended input format |
|---|---|---|
mongoexport --out f.json | NDJSON — one document per line | Auto detect or NDJSON / JSONL |
mongoexport --jsonArray | [ {...}, {...} ] | Auto detect or JSON array |
| Hand-edited single document | { ... } | Auto detect (wrapped as one row) |
Cookbook
Real mongoexport snippets and the CSV the converter produces. IDs and PII anonymised.
ObjectId and date flattened faithfully
ExampleExtended-JSON wrappers are kept, not interpreted — _id becomes _id.$oid and the date becomes created.$date.
Input (NDJSON line):
{"_id":{"$oid":"6627a1"},"name":"Ada","created":{"$date":"2026-01-02T10:00:00Z"}}
Output CSV:
_id.$oid,name,created.$date
6627a1,Ada,2026-01-02T10:00:00ZEmbedded address document to columns
ExampleA sub-document flattens into dot-notation columns, one per leaf.
Input:
[ { "name": "Ada", "address": { "city": "NYC", "zip": "10001" } } ]
Output CSV:
name,address.city,address.zip
Ada,NYC,10001Schemaless documents with differing fields
ExampleMongoDB collections rarely share a schema. The union header gives every field a column and leaves empties where a document lacks one.
Input (NDJSON):
{"name":"Ada","phone":"555-0001"}
{"name":"Grace"}
Output CSV:
name,phone
Ada,555-0001
Grace,Getting a clean _id column
ExampleIf _id.$oid is awkward, rename the structure first so the converter sees a flat _id value.
Pre-processed JSON (after json-key-renamer / restructure):
[ { "_id": "6627a1", "name": "Ada" } ]
Output CSV:
_id,name
6627a1,AdaEmbedded array as readable text
ExampleComma-joined arrays read better than JSON literals for an analyst opening the file in Excel.
Input:
[ { "name": "Ada", "tags": ["vip", "beta"] } ]
Array values = Comma joined:
name,tags
Ada,"vip, beta"Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
`_id` appears as `_id.$oid` not `_id`
By designmongoexport writes ObjectIds as {"$oid": "..."} Extended JSON. This converter flattens that wrapper rather than unwrapping it, so you get an _id.$oid column. Rename the structure first with json-key-renamer if you want a bare _id.
Dates show as `field.$date`
By designExtended-JSON dates {"$date": "..."} flatten to a <field>.$date column holding the ISO string. The value is intact and correct; it is simply under a wrapper-derived column name.
Numeric wrappers like `$numberLong`
PreservedLong integers exported as {"$numberLong": "..."} flatten to <field>.$numberLong. The value is preserved as a string so no precision is lost — restructure first if you want a plain numeric column.
Default NDJSON export with documents starting with `{`
Supportedmongoexport default output is NDJSON whose lines start with {. Auto detect handles this — it tries whole-document JSON, fails, and retries as NDJSON. Forcing NDJSON / JSONL avoids any ambiguity.
Embedded array of sub-documents
Not expandedAn array of sub-documents stays in one cell as a JSON literal — it is not split into child rows. Extract that array path with json-path-extractor and convert it separately for a row-per-element layout.
One malformed line in an NDJSON export
Invalid JSONA single corrupt document line aborts the conversion with Invalid JSON on line N. Fix or remove that line — the error tells you exactly which one.
Export larger than the free 2 MB cap
BlockedFree conversions stop at 2 MB / 500 rows. For a full collection dump, upgrade to Pro (100 MB / 100,000 rows) or export a filtered subset with a mongoexport --query.
null fields vs absent fields
By designBoth null values and absent fields render as empty cells. They are indistinguishable in the CSV — strip nulls beforehand with json-null-stripper if that distinction matters.
Frequently asked questions
Why is my `_id` column named `_id.$oid`?
Because mongoexport writes ObjectIds as Extended JSON {"$oid": "..."}, and this tool flattens that wrapper faithfully rather than unwrapping it. The hex value is intact; rename the structure first with json-key-renamer for a bare _id.
Does the converter unwrap `$date` and `$numberLong`?
No. It flattens them to field.$date / field.$numberLong columns holding the raw value. This is faithful to what mongoexport produced; pre-process the keys if you want plain columns.
Does it read default NDJSON mongoexport output?
Yes. Default mongoexport is NDJSON (one document per line). Auto detect falls back to NDJSON, or force the NDJSON / JSONL format explicitly.
What about `--jsonArray` exports?
Those convert too — the file is a JSON array, which Auto detect or the JSON array format handles directly.
How are embedded documents handled?
They flatten into dot-notation columns (address.city) when Flatten nested objects is on, which is the default. Turn it off to keep a sub-document as one JSON-string cell.
My documents have different fields — will columns still align?
Yes. The header is the union of all keys across all documents, so every field gets a column and missing values become empty cells.
What happens to embedded arrays?
They go into a single cell, serialised as JSON literal, pipe, or comma per your setting. Arrays are never expanded into extra rows.
How do I get one row per element of an embedded array?
Extract that array path first with json-path-extractor so it becomes the top-level list, then convert. Each element then maps to a row.
Is my exported data uploaded anywhere?
No. The file is parsed and converted entirely in your browser. Customer documents never reach a server.
How large an export can I convert?
Free: 2 MB / 500 rows. Pro: 100 MB / 100,000 rows. For bigger collections, export a filtered subset or upgrade.
One line in my NDJSON file is broken — what happens?
Conversion stops with Invalid JSON on line N, naming the bad line so you can fix or remove it and re-run.
I need to go the other way — CSV back into Mongo. Any tool?
Convert CSV to JSON with csv-to-json, then import with mongoimport. For NDJSON specifically, that tool's line-delimited output suits mongoimport well.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.