console
const fileInput = document.getElementById('fileInput');
const jsonPreview = document.getElementById('jsonPreview');
const dataTableBody = document.getElementById('dataTableBody');
const dataTableTr = document.getElementById('dataTableTr');
const downloadBtn = document.getElementById('downloadBtn');
const dataTable = document.getElementById('dataTable');
document.getElementById('uploadBtn').addEventListener('click', () => {
fileInput.click();
});
fileInput.addEventListener('change', function (e) {
const file = e.target.files[0];
if (!file) return;
if (file.type !== 'application/json' && !file.name.endsWith('.json')) {
jsonPreview.innerText = '请上传有效的JSON文件:';
return;
}
const reader = new FileReader();
reader.onload = function (event) {
try {
const jsonData = JSON.parse(event.target.result);
jsonPreview.innerText = JSON.stringify(jsonData, '', 2);
processData(jsonData);
downloadBtn.style.display = 'inline';
} catch (error) {
jsonPreview.innerText = '解析JSON数据时出错: ' + error.message;
downloadBtn.style.display = 'none';
}
};
reader.readAsText(file);
});
function processData(jsonData) {
const thead = dataTable.querySelector('thead');
let rows = [],cols = [],tl = thead.childElementCount;
if(!jsonData['data'] || !jsonData['data']['rows']){
thead.innerHTML = '<tr> <th>列</th> </tr>';
dataTableBody.innerHTML = `<tr><td colspan="1">没有找到数据</td></tr>`;
return;
}
rows = jsonData.data['rows'];
cols = jsonData.data['column_name'];
if(!Array.isArray(rows) || rows.length <= 0){ return; }
if(!Array.isArray(cols)){ cols = rows[0].map((v,i)=>'列'+i); }
thead.innerHTML = '<tr><th>'+cols.join('</th><th>')+'</th></tr>';
dataTableBody.innerHTML =
rows.map((r,i)=> '<tr><td>'+r.map(v=>v=='DbNull'?'':v).join('</td><td>')+'</td></tr>').join('');
}
downloadBtn.addEventListener('click', function () {
const jsonText = jsonPreview.textContent;
if (!jsonText || jsonText.includes('解析JSON')) return;
try {
const jsonData = JSON.parse(jsonText);
const csv = jsonToCsv(jsonData);
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'converted_data.csv';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch (error) {
alert('生成CSV文件时出错: ' + error.message);
}
});
function jsonToCsv(jsonData) {
let rows = [],cols = [],csv = '';
if(!jsonData['data'] || !jsonData['data']['rows']){
dataTableBody.innerHTML = `<tr><td colspan="1">没有找到数据</td></tr>`;
return csv;
}
rows = jsonData.data['rows'];
cols = jsonData.data['column_name'];
if(!Array.isArray(rows) || rows.length <= 0){ return; }
if(!Array.isArray(cols)){ cols = rows[0].map((v,i)=>'列'+i); }
csv = cols.join(',') + '\n'
+ rows.map((r,i)=> r.map(v=>v=='DbNull'?'':v).join(',')+'\n').join('');
return csv;
}
<div class="container">
<h1>JSON转CSV文件转换器</h1>
<div class="upload-section">
<button id="downloadBtn" class="download-btn">下载CSV文件</button>
<button id="uploadBtn" class="upload-btn">上传JSON文件</button>
<input type="file" id="fileInput" class="file-input" accept=".json">
<div id="errorMessage" class="error-message">请上传有效的JSON文件</div>
</div>
<div class="preview-section">
<pre id="jsonPreview" class="json-preview">
请上传JSON文件以查看预览...支持的格式:
{ "code": 0, "message": "", "data": { "column_name": [], "rows": [ [] ] } }
</pre>
<h2 class="preview-title">数据表格预览</h2>
<div class="table-container">
<table id="dataTable">
<thead>
<tr> <th>列</th> </tr>
</thead>
<tbody id="dataTableBody">
<tr>
<td>请上传JSON文件以查看表格数据...</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
:root {
--primary-color: #4a6cf7;
--secondary-color: #f0f2f5;
--text-color: #333;
--border-color: #ddd;
--success-color: #52c41a;
}
* {
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: #f5f7fa;
color: var(--text-color);
line-height: 1.6;
padding: 20px;
}
.container {
margin: 0 auto;
background: white;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
padding: 30px;
}
h1 {
color: var(--primary-color);
text-align: center;
border-bottom: 1px solid var(--border-color);
}
.upload-section {
margin-bottom: 10px;
}
.upload-btn {
background-color: var(--primary-color);
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
font-size: 14px;
transition: background-color 0.3s;
}
.upload-btn:hover {
background-color: #3a5ce7;
}
.file-input {
margin-top: 15px;
font-size: 14px;
display: none;
}
.preview-section {
margin-top: 10px;
}
.preview-title {
font-size: 18px;
margin-bottom: 15px;
color: var(--primary-color);
}
.json-preview {
background-color: #f8f9fa;
border: 1px solid var(--border-color);
border-radius: 4px;
padding: 15px;
font-family: 'Courier New', Courier, monospace;
font-size: 14px;
overflow-x: auto;
min-height: 100px;
height: 100px;
overflow: auto;
}
.download-btn {
background-color: var(--success-color);
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
font-size: 14px;
display: none;
transition: background-color 0.3s;
}
.download-btn:hover {
background-color: #43a800;
}
.error-message {
color: #f5222d;
margin-top: 10px;
display: none;
}
.table-container {
margin-top: 20px;
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
th,
td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
th {
background-color: var(--secondary-color);
font-weight: 600;
}
tbody {
height: 500px;
overflow-y: auto;
display: block;
}
tbody tr,
thead tr {
display: table;
}
tr:hover {
background-color: var(--secondary-color);
}
@media (max-width: 600px) {
.container {
padding: 20px;
}
h1 {
font-size: 22px;
}
.upload-btn,
.download-btn {
padding: 10px 20px;
font-size: 14px;
}
}