If you work with data in any capacity—whether you are building APIs, configuring infrastructure, importing spreadsheet exports into a database, or wrangling analytics data—you will inevitably need to convert between data formats. JSON, CSV, XML, and YAML each have their own strengths and weaknesses, and knowing how to move data between them cleanly is a fundamental skill.
This guide covers every major conversion path between these four formats. For each one, you will get a clear explanation of what changes structurally during the conversion, a working code example you can copy and adapt, the most common pitfalls that cause data loss or breakage, and a link to a free tool that handles it instantly in your browser.
Understanding the Four Formats
Before diving into conversions, it helps to understand what makes each format distinct. They all represent structured data, but they differ dramatically in their syntax, readability, and intended use cases.
JSON (JavaScript Object Notation)
JSON is the lingua franca of web development. It supports objects (key-value pairs), arrays, strings, numbers, booleans, and null. It is compact, fast to parse, and natively understood by JavaScript. Nearly every modern API speaks JSON.
{
"name": "Alice Chen",
"age": 32,
"roles": ["developer", "team-lead"],
"address": {
"city": "Berlin",
"country": "Germany"
}
}
Best for: APIs, web applications, NoSQL databases, data interchange between services.
Try NexTool's JSON Formatter →CSV (Comma-Separated Values)
CSV is the oldest and simplest format on this list. It represents tabular data—rows and columns—with commas separating values and newlines separating rows. The first row is typically a header. CSV has no native support for nested structures, data types, or metadata.
name,age,role,city,country
Alice Chen,32,developer,Berlin,Germany
Bob Smith,28,designer,London,UK
Carol Wu,35,manager,Tokyo,Japan
Best for: Spreadsheet imports/exports, database dumps, data analysis, bulk data transfer, legacy systems.
Try NexTool's CSV Formatter →XML (Extensible Markup Language)
XML uses a tag-based syntax similar to HTML. It supports attributes, namespaces, schema validation (via XSD), and can represent deeply nested, complex document structures. It is verbose but extremely well-specified, which is why it remains the backbone of many enterprise systems.
<employees>
<employee id="1">
<name>Alice Chen</name>
<age>32</age>
<roles>
<role>developer</role>
<role>team-lead</role>
</roles>
<address city="Berlin" country="Germany" />
</employee>
</employees>
Best for: SOAP APIs, enterprise integrations, document formats (SVG, RSS, XHTML), systems requiring schema validation, configuration where attributes matter.
Try NexTool's XML Formatter →YAML (YAML Ain't Markup Language)
YAML is a superset of JSON that uses indentation instead of braces and brackets. It supports comments, multi-line strings, and anchors/aliases for reusing values. Its readability makes it the default choice for configuration files.
employees:
- name: Alice Chen
age: 32
roles:
- developer
- team-lead
address:
city: Berlin
country: Germany
Best for: Configuration files (Docker Compose, Kubernetes, GitHub Actions, Ansible), human-editable structured data, CI/CD pipelines.
Try NexTool's YAML Formatter →Format Comparison at a Glance
This table summarizes the key differences that matter when you are choosing a format or planning a conversion.
| Feature | JSON | CSV | XML | YAML |
|---|---|---|---|---|
| Readability | Good | Excellent (tabular) | Fair (verbose) | Excellent |
| Nesting support | Yes | No | Yes | Yes |
| Comments | No | No | Yes | Yes |
| Data types | String, number, bool, null, array, object | Everything is a string | String (types via schema) | String, number, bool, null, array, object |
| Schema validation | JSON Schema | No standard | XSD, DTD, RelaxNG | No standard |
| File size | Compact | Very compact | Large (verbose tags) | Compact |
| Parse speed | Fast | Very fast | Moderate | Slower |
| Primary use | APIs, web apps | Tabular data, spreadsheets | Enterprise, documents | Configuration files |
JSON to CSV Conversion
This is by far the most common conversion developers need. You have an API response or a JSON dataset, and you need to get it into a spreadsheet, import it into a database, or hand it to a data analyst who works in Excel.
How It Works
JSON to CSV conversion maps each object in a JSON array to a row, with the object keys becoming column headers. Here is a straightforward example:
// Input: JSON array of flat objects
[
{"name": "Alice", "age": 32, "city": "Berlin"},
{"name": "Bob", "age": 28, "city": "London"},
{"name": "Carol", "age": 35, "city": "Tokyo"}
]
// Output: CSV
name,age,city
Alice,32,Berlin
Bob,28,London
Carol,35,Tokyo
This works cleanly when your JSON objects are flat—no nested objects or arrays. But real-world JSON is rarely that simple.
The Nested JSON Problem
The single biggest pitfall in JSON-to-CSV conversion is nested data. CSV is inherently flat. When your JSON contains nested objects or arrays, you have three choices:
- Dot-notation flattening —
address.citybecomes a column header. This preserves structure but creates wide tables. - JSON stringification — The nested value is serialized as a JSON string inside the CSV cell. Useful as a lossless fallback, but ugly in spreadsheets.
- Array expansion — Each array element gets its own row. This multiplies your row count but keeps each cell atomic.
// Input: JSON with nesting
[
{
"name": "Alice",
"address": {"city": "Berlin", "zip": "10115"},
"roles": ["developer", "team-lead"]
}
]
// Output Option 1: Dot-notation flattening
name,address.city,address.zip,roles
Alice,Berlin,10115,"developer,team-lead"
// Output Option 2: JSON stringification
name,address,roles
Alice,"{""city"":""Berlin"",""zip"":""10115""}","[""developer"",""team-lead""]"
// Output Option 3: Array expansion (one row per role)
name,address.city,address.zip,role
Alice,Berlin,10115,developer
Alice,Berlin,10115,team-lead
Key takeaway: Before converting JSON to CSV, decide on your flattening strategy. Dot-notation works for most cases. If you need the CSV to be imported into a spreadsheet for human review, avoid stringified JSON in cells—it is nearly unreadable. If you have arrays that represent one-to-many relationships, consider whether row expansion or comma-delimited values within a cell makes more sense for your downstream use.
Common Pitfalls
- Inconsistent keys across objects. If object A has keys
name, age, cityand object B has keysname, email, phone, your CSV needs to be a union of all keys, with empty cells where data is missing. - Commas and quotes inside values. If a value contains a comma, it must be wrapped in double quotes. If it contains a double quote, that quote must be escaped by doubling it (
""). Many hand-rolled converters get this wrong. - Encoding issues. JSON is always UTF-8. CSV files opened in Excel on Windows often expect UTF-8 with BOM (byte order mark). Without the BOM, non-ASCII characters like umlauts or emoji may render as garbage. Add
\uFEFFat the beginning of your CSV if you are targeting Excel. - Null vs. empty string. JSON distinguishes between
nulland"". CSV does not. Both become an empty cell. If this distinction matters, you will need a convention (e.g., the literal stringNULL).
CSV to JSON Conversion
Going the other direction is typically simpler. You have tabular data and need to get it into a structured format for an API, a NoSQL database, or a JavaScript application.
How It Works
The header row becomes the keys, and each subsequent row becomes an object. The result is an array of objects.
// Input: CSV
name,age,department,salary
Alice,32,Engineering,95000
Bob,28,Design,82000
Carol,35,Management,105000
// Output: JSON (array of objects)
[
{"name": "Alice", "age": "32", "department": "Engineering", "salary": "95000"},
{"name": "Bob", "age": "28", "department": "Design", "salary": "82000"},
{"name": "Carol", "age": "35", "department": "Management", "salary": "105000"}
]
The Type Inference Problem
Notice that age and salary in the JSON output are strings, not numbers. CSV has no type system—everything is text. A good converter will try to infer types: numbers become numbers, true/false become booleans, empty cells become null. But automatic type inference can backfire.
Consider a CSV column called zipcode with values like 01234. A naive converter will parse that as the integer 1234, stripping the leading zero. ZIP codes, phone numbers, product SKUs, and any identifier that happens to look like a number should stay as strings.
Rule of thumb: Only infer numeric types for columns that are genuinely quantities (age, price, count). When in doubt, keep it as a string. It is far easier to parse a string into a number downstream than to recover a leading zero that was silently stripped.
Reconstructing Nested Structures
If your CSV was originally flattened from nested JSON using dot-notation (e.g., address.city, address.zip), a smart converter can reconstruct the nesting:
// Input: CSV with dot-notation headers
name,address.city,address.zip,address.country
Alice,Berlin,10115,Germany
// Output: Reconstructed nested JSON
{
"name": "Alice",
"address": {
"city": "Berlin",
"zip": "10115",
"country": "Germany"
}
}
This is a powerful feature, but it requires the converter to recognize the dot-notation convention. Not all tools support it.
Try NexTool's CSV to JSON Converter →JSON to YAML (and YAML to JSON)
This is the most straightforward conversion on this list because YAML is a superset of JSON. Every valid JSON document is already valid YAML. The conversion is essentially a syntax transformation—no data is gained or lost.
JSON to YAML
// Input: JSON
{
"server": {
"host": "0.0.0.0",
"port": 8080,
"ssl": true
},
"database": {
"url": "postgres://localhost:5432/mydb",
"pool_size": 10,
"timeout": 30
},
"features": ["auth", "logging", "rate-limiting"]
}
# Output: YAML
server:
host: "0.0.0.0"
port: 8080
ssl: true
database:
url: "postgres://localhost:5432/mydb"
pool_size: 10
timeout: 30
features:
- auth
- logging
- rate-limiting
The YAML version is more readable, supports inline comments (which JSON does not), and is the expected format for tools like Docker Compose, Kubernetes manifests, and GitHub Actions workflows.
YAML to JSON
Going from YAML to JSON is necessary when you need to send configuration data to an API, use it in JavaScript, or validate it with a JSON Schema. The conversion strips comments and converts the indentation-based structure to braces and brackets.
Pitfalls in YAML/JSON Conversion
- YAML's "Norway problem." In YAML 1.1, the bare value
NOis interpreted as booleanfalse(because YAML considersyes/no,on/off, andtrue/falseas booleans). This caused real production bugs when country codes likeNO(Norway) were silently converted tofalse. YAML 1.2 fixed this, but many parsers still use 1.1 rules. Always quote strings that could be misinterpreted:"NO","yes","on". - Multi-line strings. YAML supports literal (
|) and folded (>) block scalars for multi-line text. When converting to JSON, these become a single string with\ncharacters. The data is preserved, but the readability is lost. - Anchors and aliases. YAML allows you to define a value once (
&anchor) and reference it elsewhere (*anchor). JSON has no equivalent. During conversion, anchors are resolved (the referenced value is duplicated inline), which can significantly increase file size for heavily aliased YAML. - Comments are lost. JSON does not support comments. Any YAML comments are permanently discarded during conversion. If those comments contain important context, document it elsewhere before converting.
JSON to XML (and XML to JSON)
Converting between JSON and XML is trickier than it looks because the two formats have fundamentally different data models. XML has concepts—attributes, namespaces, mixed content (text interleaved with elements), processing instructions—that have no direct equivalent in JSON.
JSON to XML
// Input: JSON
{
"employees": [
{"name": "Alice", "age": 32, "department": "Engineering"},
{"name": "Bob", "age": 28, "department": "Design"}
]
}
<!-- Output: XML -->
<?xml version="1.0" encoding="UTF-8"?>
<root>
<employees>
<item>
<name>Alice</name>
<age>32</age>
<department>Engineering</department>
</item>
<item>
<name>Bob</name>
<age>28</age>
<department>Design</department>
</item>
</employees>
</root>
Notice how the JSON array becomes repeated <item> elements. The wrapper element name (item) is a convention—different converters use different names (element, entry, or the parent's singular form).
XML to JSON
Converting XML to JSON requires making decisions about how to handle XML-specific features:
- Attributes: Commonly prefixed with
@or-in the JSON output (e.g.,<employee id="1">becomes{"@id": "1"}). - Text content with attributes: When an element has both attributes and text content, the text is often stored under a special key like
#text(e.g.,<price currency="USD">29.99</price>becomes{"@currency": "USD", "#text": "29.99"}). - Single vs. repeated elements: If
<roles><role>dev</role></roles>has a singlerole, should it be a string or a one-element array? This ambiguity is a constant source of bugs. Consistent converters always use arrays for elements that can repeat.
Pro tip: When converting XML to JSON, always verify that array-type elements are consistently arrays, even when they contain only one item. APIs that sometimes return a single object and sometimes return an array for the same field are a notorious source of runtime errors.
CSV to XML (and XML to CSV)
These conversions are less common but still come up regularly in enterprise contexts, ETL pipelines, and legacy system integrations.
CSV to XML
Each CSV row becomes an XML element, with column headers becoming child element names:
<!-- From the CSV: name,age,city -->
<?xml version="1.0" encoding="UTF-8"?>
<records>
<record>
<name>Alice</name>
<age>32</age>
<city>Berlin</city>
</record>
<record>
<name>Bob</name>
<age>28</age>
<city>London</city>
</record>
</records>
XML to CSV
Going from XML to CSV has the same flattening challenges as JSON to CSV, plus the additional complication of attributes. Attributes and nested elements both need to be flattened into columns. A common approach is element@attribute notation for attribute columns.
CSV to YAML (and YAML to CSV)
These conversions are essentially two-step processes: CSV to JSON to YAML, and YAML to JSON to CSV. Since YAML and JSON are structurally equivalent, the real conversion happens in the CSV/JSON step.
# CSV to YAML output
records:
- name: Alice
age: 32
city: Berlin
- name: Bob
age: 28
city: London
YAML to CSV requires the same flattening decisions as JSON to CSV. If your YAML contains deeply nested configuration, flattening it into a table may not be meaningful.
Decision Guide: Which Format Should You Use?
Choosing the right format upfront saves you from painful conversions later. Here is a decision framework based on real-world constraints:
Use JSON when:
- You are building or consuming a REST API
- Your data will be used in a JavaScript/TypeScript application
- You need nested structures and the consumer understands JSON natively
- You are storing data in MongoDB, CouchDB, or another document database
- File size and parse speed matter
Use CSV when:
- Your data is genuinely tabular (rows and columns with no nesting)
- The data will be opened in Excel, Google Sheets, or a similar tool
- You need to import/export data from a relational database
- You are dealing with large datasets (millions of rows) where file size matters
- Non-technical stakeholders need to read or edit the data
Use XML when:
- You are integrating with a system that requires XML (SOAP APIs, legacy enterprise systems)
- You need schema validation with XSD
- You are working with document formats (SVG, RSS, EPUB, XHTML)
- Attributes are a natural fit for your data model (e.g.,
<price currency="USD">) - You need namespaces to avoid naming collisions
Use YAML when:
- Humans will frequently read and edit the files
- You need inline comments to explain configuration choices
- You are working with DevOps tools (Docker, Kubernetes, Ansible, GitHub Actions)
- Readability is more important than parse speed
When all else is equal: Default to JSON. It has the widest tooling support, the fastest parsers, reasonable readability, and works everywhere. Only reach for another format when JSON's limitations (no comments, no tabular representation, too verbose for pure config) actually hurt your use case.
Practical Tips for Clean Conversions
Regardless of which direction you are converting, these practices will save you from the most common bugs:
- Validate before converting. A malformed input will produce a broken output. Run your data through a formatter or validator first. If your JSON has a trailing comma or your CSV has an unescaped quote, fix it before attempting conversion.
- Handle encoding explicitly. Always work in UTF-8. If your source data comes from a legacy system using Latin-1 or Windows-1252, convert the encoding first. Mixing encodings is the number-one cause of garbled characters.
- Preserve data types intentionally. When converting from a typed format (JSON, YAML) to an untyped one (CSV), document your type conventions. When converting back, apply type inference carefully and test edge cases like leading zeros, scientific notation (
1e10), and date strings. - Round-trip test your conversions. Convert A to B, then convert B back to A. If the result does not match the original, you have data loss somewhere. This is especially important for JSON to CSV, where nesting and types are lost.
- Use browser-based tools for quick conversions. For one-off conversions, you do not need to write code. Paste your data into a converter tool, get the output, and move on. Save the scripting for automated pipelines.
Code Examples: Conversion in JavaScript
If you need to automate conversions in code, here are production-ready JavaScript snippets for the most common paths.
JSON Array to CSV
function jsonToCsv(jsonArray) {
if (!jsonArray.length) return '';
// Collect all unique keys across all objects
const headers = [...new Set(jsonArray.flatMap(obj => Object.keys(obj)))];
// Escape a single CSV value
const escape = (val) => {
if (val === null || val === undefined) return '';
const str = typeof val === 'object' ? JSON.stringify(val) : String(val);
// Wrap in quotes if it contains comma, quote, or newline
if (str.includes(',') || str.includes('"') || str.includes('\n')) {
return '"' + str.replace(/"/g, '""') + '"';
}
return str;
};
const rows = jsonArray.map(obj =>
headers.map(h => escape(obj[h])).join(',')
);
return [headers.join(','), ...rows].join('\n');
}
// Usage
const data = [
{ name: 'Alice', age: 32, city: 'Berlin' },
{ name: 'Bob', age: 28, city: 'London' }
];
console.log(jsonToCsv(data));
// name,age,city
// Alice,32,Berlin
// Bob,28,London
CSV to JSON Array
function csvToJson(csv) {
const lines = csv.trim().split('\n');
const headers = parseCsvLine(lines[0]);
return lines.slice(1).map(line => {
const values = parseCsvLine(line);
const obj = {};
headers.forEach((h, i) => {
obj[h] = values[i] || '';
});
return obj;
});
}
// Handles quoted fields with commas and escaped quotes
function parseCsvLine(line) {
const result = [];
let current = '';
let inQuotes = false;
for (let i = 0; i < line.length; i++) {
const char = line[i];
if (inQuotes) {
if (char === '"' && line[i + 1] === '"') {
current += '"';
i++; // skip escaped quote
} else if (char === '"') {
inQuotes = false;
} else {
current += char;
}
} else {
if (char === '"') {
inQuotes = true;
} else if (char === ',') {
result.push(current);
current = '';
} else {
current += char;
}
}
}
result.push(current);
return result;
}
// Usage
const csv = `name,age,city
Alice,32,Berlin
Bob,28,London`;
console.log(csvToJson(csv));
// [{ name: 'Alice', age: '32', city: 'Berlin' }, ...]
Flatten Nested JSON (Dot-Notation)
function flattenObject(obj, prefix = '') {
const result = {};
for (const [key, value] of Object.entries(obj)) {
const newKey = prefix ? `${prefix}.${key}` : key;
if (value && typeof value === 'object' && !Array.isArray(value)) {
Object.assign(result, flattenObject(value, newKey));
} else if (Array.isArray(value)) {
// Join arrays as comma-separated string
result[newKey] = value.join(', ');
} else {
result[newKey] = value;
}
}
return result;
}
// Usage
const nested = {
name: 'Alice',
address: { city: 'Berlin', zip: '10115' },
roles: ['developer', 'team-lead']
};
console.log(flattenObject(nested));
// {
// name: 'Alice',
// 'address.city': 'Berlin',
// 'address.zip': '10115',
// roles: 'developer, team-lead'
// }
Combine flattenObject with jsonToCsv to handle nested JSON-to-CSV conversion: first flatten each object, then convert the flat array to CSV.
Frequently Asked Questions
Can I convert JSON to CSV without losing data?
For flat JSON (no nesting), yes—the conversion is lossless in both directions. For nested JSON, some information is inevitably restructured. You can minimize loss by using dot-notation flattening for objects and a delimiter for arrays. The key is to have a consistent, reversible convention so you can reconstruct the original structure if needed.
What is the fastest way to convert a small file right now?
Use a browser-based tool. Paste your data, click convert, copy the result. No installation, no code, no dependencies. NexTool offers free converters for every combination discussed in this article, and all processing happens locally in your browser—your data never leaves your machine.
How do I handle large files (100MB+)?
Browser-based tools work well for files up to a few megabytes. For larger files, use a streaming approach in code. In Node.js, libraries like csv-parser and JSONStream process data row-by-row without loading the entire file into memory. For XML, use a SAX parser instead of a DOM parser.
Is YAML safer than JSON for configuration?
YAML is more readable but has more parsing edge cases (the Norway problem, type coercion, indentation sensitivity). JSON is stricter and less error-prone. For configuration that will be edited by humans, YAML is often preferred despite its quirks. For configuration generated by machines, JSON is safer. Many teams use YAML for source files and validate by converting to JSON before deployment.