125 lines
3.7 KiB
HTML
125 lines
3.7 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang="en">
|
||
|
|
||
|
<head>
|
||
|
<meta charset="UTF-8">
|
||
|
<title>Flatten JSON</title>
|
||
|
<style>
|
||
|
body {
|
||
|
font-family: Arial, sans-serif;
|
||
|
margin: 20px;
|
||
|
}
|
||
|
</style>
|
||
|
</head>
|
||
|
|
||
|
<body>
|
||
|
<h2>Upload JSON to Flatten</h2>
|
||
|
<input type="file" id="upload" accept=".json">
|
||
|
<button id="export-csv">Export as CSV</button>
|
||
|
<h3>Flattened JSON:</h3>
|
||
|
<pre id="output"></pre>
|
||
|
|
||
|
<script>
|
||
|
document.getElementById('upload').addEventListener('change', function (event) {
|
||
|
const fileName = event.target.files[0].name;
|
||
|
const fileReader = new FileReader();
|
||
|
|
||
|
fileReader.onload = function () {
|
||
|
try {
|
||
|
const json = JSON.parse(fileReader.result);
|
||
|
const flattenedJson = flattenJson(json);
|
||
|
document.getElementById('output').textContent = JSON.stringify(flattenedJson, null, 2);
|
||
|
const outputFileName = `${fileName.split('.')[0]}_flattened.csv`; // Dynamic output file name
|
||
|
document.getElementById('export-csv').setAttribute('download', outputFileName);
|
||
|
} catch (e) {
|
||
|
document.getElementById('output').textContent = 'Error parsing JSON: ' + e;
|
||
|
}
|
||
|
};
|
||
|
fileReader.readAsText(event.target.files[0]);
|
||
|
});
|
||
|
|
||
|
|
||
|
function flattenJson(obj) {
|
||
|
const result = [];
|
||
|
|
||
|
obj.forEach((item, index) => {
|
||
|
const flattenedItem = {};
|
||
|
|
||
|
function flatten(item, prefix = '') {
|
||
|
if (typeof item !== 'object' || item === null) {
|
||
|
flattenedItem[prefix] = item;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (const key in item) {
|
||
|
let newKey = prefix ? `${prefix}_${key}` : key;
|
||
|
|
||
|
if (Array.isArray(item[key])) {
|
||
|
item[key].forEach((subItem, subIndex) => {
|
||
|
flatten(subItem, `${newKey}_obj_${subIndex + 1}`);
|
||
|
});
|
||
|
} else if (typeof item[key] === 'object' && item[key] !== null) {
|
||
|
flatten(item[key], newKey);
|
||
|
} else {
|
||
|
flattenedItem[newKey] = item[key];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
flatten(item);
|
||
|
result.push(flattenedItem);
|
||
|
});
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
// output
|
||
|
document.getElementById('export-csv').addEventListener('click', function () {
|
||
|
const flattenedJson = JSON.parse(document.getElementById('output').textContent);
|
||
|
const csvContent = convertJsonToCsv(flattenedJson);
|
||
|
const fileNameWithoutExtension = document.getElementById('upload').files[0].name.split('.')[0];
|
||
|
const outputFileName = `${fileNameWithoutExtension}_flattened.csv`;
|
||
|
downloadCsv(csvContent, outputFileName);
|
||
|
});
|
||
|
|
||
|
|
||
|
function validateCSV(json) {
|
||
|
for (const key in json) {
|
||
|
const value = json[key];
|
||
|
// check: commas, double quotes, line breaks
|
||
|
if (typeof value === 'string' && (value.includes(',') || value.includes('"') || value.includes('\n'))) {
|
||
|
// escape special chars
|
||
|
json[key] = `"${value.replace(/"/g, '""')}"`;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function convertJsonToCsv(json) {
|
||
|
const keys = Object.keys(json[0]);
|
||
|
const headerRow = keys.join(',') + '\n';
|
||
|
|
||
|
let dataRows = '';
|
||
|
json.forEach(obj => {
|
||
|
const values = keys.map(key => obj[key]);
|
||
|
dataRows += values.join(',') + '\n';
|
||
|
});
|
||
|
|
||
|
return headerRow + dataRows;
|
||
|
}
|
||
|
|
||
|
function downloadCsv(csvContent, fileName) {
|
||
|
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
||
|
const link = document.createElement('a');
|
||
|
const url = URL.createObjectURL(blob);
|
||
|
|
||
|
link.setAttribute('href', url);
|
||
|
link.setAttribute('download', fileName);
|
||
|
link.style.visibility = 'hidden';
|
||
|
document.body.appendChild(link);
|
||
|
link.click();
|
||
|
document.body.removeChild(link);
|
||
|
}
|
||
|
</script>
|
||
|
</body>
|
||
|
|
||
|
</html>
|