How to convert csv to json for power bi and tableau
- Step 1Export the dataset as CSV — From your finance/ops system or spreadsheet, export a CSV with a header row. Headers become field names that surface as column names in Power BI / Tableau, so name them report-friendly.
- Step 2Drop the CSV onto the converter above — Accepts
.csv,.tsv,.txt. PapaParse auto-detects the delimiter and is quote-aware, so an amount like"1,234.56"(thousands separator inside quotes) stays one field. - Step 3Choose Array for a flat table, Grouped for a hierarchy — Array of objects loads as a flat table — the usual BI case. Grouped by column keys records under a dimension (region, department) for a hierarchical load the navigator expands.
- Step 4Keep type inference on for clean modeling — Leave Infer numbers, booleans, null on so measures arrive numeric and flags boolean. Turn it off if you would rather do all typing inside Power Query / Tableau (every field then loads as text).
- Step 5Pick an indent (cosmetic) and download — Indent does not affect the load. Download JSON, save it where the connector can reach it. For Power BI: Get Data → JSON → point at the file. For Tableau: Connect → JSON file.
- Step 6Verify types in the model — After loading, check the column types in Power BI's model view / Tableau's data pane. With inference on, numbers and booleans should already be typed; fix any column the connector still guessed wrong with a single type change.
Output mode → BI load shape
The tool produces the JSON; you point the connector at it.
| Output mode | Shape | BI result |
|---|---|---|
| Array of objects | [ {row}, {row} ] | Flat table of rows |
| Grouped by column | { "Region": [ {row} ] } | Hierarchy the navigator expands per key |
| NDJSON | one object per line | Not the standard BI JSON shape — use Array |
Inference → BI column type
Inference is global. Off loads every column as text, leaving typing to the BI tool.
| CSV cell | JSON (inference on) | BI column type | Note |
|---|---|---|---|
1234.56 | 1234.56 | Decimal number | Measure-ready |
42 | 42 | Whole number | Safe integers only |
true | true | True/False | Boolean flag |
null | null | blank / null | Distinct from empty text |
0042 (GL code) | 42 | number | Leading zero lost — turn inference off for codes |
2026-06-12 | "2026-06-12" | text (ISO) | Set a Date type in the model |
Cookbook
Recipes for feeding Power BI's JSON connector and Tableau's JSON data source.
Flat table for the Power BI JSON connector
ExampleDefault array, inference on. Revenue is a number and closed a boolean, so the model types them without manual steps.
Input (deals.csv):
deal,revenue,closed
A,12000,true
B,3500,false
Output (array, inference on):
[
{ "deal": "A", "revenue": 12000, "closed": true },
{ "deal": "B", "revenue": 3500, "closed": false }
]
→ Get Data → JSON → select this fileHierarchy grouped by region
ExampleGrouped mode keys records under region so the navigator can expand a per-region structure.
Input:
customer,region,revenue
Acme,EMEA,12000
Globex,EMEA,8000
Initech,APAC,5000
Output (Grouped by column: region):
{
"EMEA": [ { "customer": "Acme", "region": "EMEA", "revenue": 12000 }, … ],
"APAC": [ { "customer": "Initech", "region": "APAC", "revenue": 5000 } ]
}Keep a GL / cost-centre code as a string
ExampleAccounting codes with leading zeros must stay exact. Turn inference off so they are clean dimension keys.
Input:
account,amount
0042,1500
Output (inference OFF):
[ { "account": "0042", "amount": "1500" } ]
→ account loads as a text dimension '0042'Null measure vs empty string
ExampleA literal null keeps a measure column numeric with a blank value; an empty string would force the column to text.
Input:
month,sales
Jan,1000
Feb,null
Output:
[ { "month": "Jan", "sales": 1000 }, { "month": "Feb", "sales": null } ]
→ sales stays a numeric measure with a blank for FebDate column to type in the model
ExampleDates load as ISO text; set the column to Date in Power BI / Tableau. The converter does not emit a date type.
Output element:
{ "order": "A", "placed": "2026-06-12" }
→ in Power Query: Transform → Data Type → DateErrors 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.
Accounting code loses leading zeros
By designA GL or cost-centre code 0042 becomes 42 with inference on, breaking the dimension key. Turn off Infer numbers, booleans, null so codes stay strings. Inference is global, so if your dataset mixes codes (want text) and measures (want numeric), convert with inference off and set numeric types in Power Query, or pre-clean the code column.
Date column loads as text
Expected2026-06-12 stays a JSON string, so the BI tool loads it as text. Set the column's data type to Date in Power Query / Tableau (BI tools parse ISO dates reliably). The converter cannot emit a native date type because JSON has none.
Thousands-separated amount stays text
ExpectedAn amount written "1,234.56" (comma thousands separator, inside quotes so it is one cell) does not match the numeric pattern, so it stays a string and loads as text. Strip the separator first (e.g. with csv-find-replace, comma → empty in that column) so it becomes a real number.
BI navigator still guesses a type wrong
BI behaviourPower BI's JSON navigator does its own type inference on top of the JSON values; occasionally it picks the wrong type for a mostly-numeric column with one outlier. The JSON faithfully reflects the cells — fix it with one Changed Type step in Power Query. Inference on minimizes how often this happens.
NDJSON is not the standard BI JSON shape
Use ArrayPower BI's JSON connector and Tableau's JSON source expect an array (or grouped object), not newline-delimited records. Use Array or Grouped mode for BI. NDJSON is for warehouse/streaming loads, not these connectors.
Grouped key column still inside each record
By designWhen you group by region, each record keeps its region field as well as being under the region key — handy for BI, since the field is available as a column after the navigator expands the group. Remove it first with csv-column-remover only if you specifically don't want the duplicate.
Empty cell becomes empty string, not blank measure
ExpectedA blank numeric cell becomes "" (empty string) with default settings, which can coerce a measure column to text in BI. Use a literal null cell for true nulls, or turn on Skip empty cells so the field is omitted and the column stays numeric with a blank.
Free tier file/row cap on a big extract
LimitFree tier caps at 2 MB / 500 rows — fine for a small report, not a full extract. Pro raises it to 100 MB / 100,000 rows. For very large datasets, the warehouse path (NDJSON → BigQuery/Snowflake → DirectQuery) usually beats a single JSON file; see the warehouse NDJSON guide.
Frequently asked questions
Which output mode does Power BI's JSON connector want?
An array of objects — use Array of objects mode. Power BI's JSON connector and Tableau's JSON data source read a JSON array (or a grouped object for a hierarchy). Do not use NDJSON for these connectors; that format is for warehouse/streaming loads.
Why convert to JSON instead of importing the CSV directly?
JSON with inference on gives the model real number and boolean types up front, and JSON null is distinct from empty string for nullable measures. A raw CSV often loads every column as text or mis-types a column with one stray value, forcing manual Changed Type steps. JSON also expresses hierarchy (grouped mode) that a flat CSV cannot.
How do I keep GL / cost-centre codes as text dimensions?
Turn off type inference so codes like 0042 stay strings. With inference on they become numbers and lose leading zeros. The trade-off is measures also become text — set their numeric types in Power Query, or pre-clean just the code column.
Will date columns load as a Date type?
No — dates stay ISO strings and load as text. Set the column's data type to Date in Power Query or Tableau, which parse ISO-8601 dates reliably. The converter cannot emit a native date type because JSON has none.
How do I load a hierarchy like sales by region?
Use Grouped by column mode and pick the region (or department) column. The output keys records under each region value, and Power BI's navigator can expand that structure into a hierarchical load. Each record keeps its grouping field as a column too.
Why is my amount column loading as text?
Likely a thousands separator: "1,234.56" does not match the numeric pattern and stays a string. Strip the comma with csv-find-replace on that column before converting so it becomes a real number that loads as a decimal measure.
Is my financial data uploaded during conversion?
No. PapaParse parses and the JSON is built in your browser; the data never reaches a JAD Apps server. Only an anonymous run counter is recorded when signed in, with opt-out available.
How do I avoid an empty cell coercing my measure to text?
An empty numeric cell becomes "" by default, which can flip the column to text in BI. Either use a literal null cell for true nulls, or turn on Skip empty cells so the field is omitted and the measure column stays numeric with a blank value.
How large a dataset can I convert for BI?
Free: 2 MB / 500 rows. Pro: 100 MB / 100,000 rows. Pro+Media: 500 MB / 500,000 rows. Developer: 5 GB, no row cap. For very large extracts, a warehouse load with DirectQuery usually beats a single JSON file — see the warehouse NDJSON guide.
Can I inspect the JSON before loading it into Power BI?
The preview pane shows the first 1.5 KB. For a fuller look at a grouped hierarchy, run the download through json-tree-viewer, or validate it is well-formed with json-validator.
Can I generate a schema for governance / documentation?
Yes — feed the converted array to json-schema-generator for a JSON Schema you can keep alongside the dataset for documentation or validation in a pipeline.
Can I automate the conversion as a scheduled refresh source?
Yes. Pair the @jadapps/runner once and POST the CSV to 127.0.0.1:9789/v1/tools/csv-to-json/run. A pattern: scheduled finance export → runner converts to JSON in a shared folder → Power BI refreshes from that file. Data stays on your machine and never reaches JAD's servers.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.