大更新,太多了,具体进游戏查看详细更新内容

反正很多
This commit is contained in:
2025-05-27 11:09:09 +08:00
parent a1e71a6a79
commit 8215cfa3ee
382 changed files with 13838 additions and 2974 deletions

100
Server/JsonEdit/README.md Normal file
View File

@@ -0,0 +1,100 @@
# JSON 批量编辑器
一个简洁强大的JSON编辑工具专门用于批量添加键值对到JSON文件中的所有对象。
## 🚀 功能特点
- **批量添加属性**: 一键为JSON中所有对象添加新的键值对
- **智能类型识别**: 自动识别并转换数据类型
- **支持所有JSON数据类型**: 字符串、数字、布尔值、对象、数组、null
- **文件上传**: 支持JSON文件拖拽上传
- **即时下载**: 编辑完成后立即下载修改后的JSON文件
- **无需服务器**: 纯前端实现,直接在浏览器中运行
## 📋 支持的数据类型
| 类型 | 输入示例 | 转换结果 |
|------|----------|----------|
| 字符串 | `hello world` | `"hello world"` |
| 整数 | `123` | `123` |
| 小数 | `3.14` | `3.14` |
| 布尔值 | `true``false` | `true``false` |
| 空值 | `null` | `null` |
| 对象 | `{"key": "value"}` | `{"key": "value"}` |
| 数组 | `[1, 2, 3]` | `[1, 2, 3]` |
| 空字符串 | *(留空)* | `""` |
## 🎯 使用方法
### 1. 加载JSON数据
- **方法一**: 点击"上传JSON文件"按钮选择文件
- **方法二**: 直接在编辑器中粘贴JSON数据
- **方法三**: 点击"加载示例数据"使用预设数据
### 2. 批量添加属性
1. 在"键名"字段输入要添加的属性名,如: `能否购买`
2. 在"键值"字段输入属性值,如: `true`
3. 点击"批量添加到所有对象"按钮
4. 系统会自动为JSON中的每个对象添加该属性
### 3. 下载结果
点击"下载修改后的JSON"按钮保存编辑后的文件
## 💡 使用示例
### 原始JSON:
```json
{
"小麦": {
"花费": 120,
"收益": 100,
"品质": "普通"
},
"稻谷": {
"花费": 100,
"收益": 120,
"品质": "普通"
}
}
```
### 添加属性: 键名=`能否购买`, 键值=`true`
### 结果JSON:
```json
{
"小麦": {
"花费": 120,
"收益": 100,
"品质": "普通",
"能否购买": true
},
"稻谷": {
"花费": 100,
"收益": 120,
"品质": "普通",
"能否购买": true
}
}
```
## 🔧 快速开始
1. 直接在浏览器中打开 `templates/json_editor.html` 文件
2. 无需安装任何依赖或服务器
3. 开始使用批量编辑功能
## ⚠️ 注意事项
- 工具会递归处理嵌套对象,为所有找到的对象添加指定属性
- 数组元素如果是对象,也会被添加属性
- 确保JSON格式正确否则无法处理
- 修改前建议备份原始文件
## 🎨 界面说明
- **左侧边栏**: 文件操作、批量编辑功能、快速示例
- **右侧编辑区**: JSON数据显示和编辑
- **智能提示**: 实时显示操作结果和错误信息
这个工具特别适合游戏开发、配置文件管理等需要批量修改JSON数据的场景。

View File

@@ -0,0 +1,65 @@
# JSON格式化示例
以下展示三种不同的JSON格式化效果
## 原始数据
```json
{"小麦":{"花费":120,"收益":100,"品质":"普通"},"稻谷":{"花费":100,"收益":120,"品质":"普通"}}
```
## 1. 标准格式化2空格缩进
```json
{
"小麦": {
"花费": 120,
"收益": 100,
"品质": "普通"
},
"稻谷": {
"花费": 100,
"收益": 120,
"品质": "普通"
}
}
```
## 2. 最小化(压缩)
```json
{"小麦":{"花费":120,"收益":100,"品质":"普通"},"稻谷":{"花费":100,"收益":120,"品质":"普通"}}
```
## 3. 一行化(一个对象一行)
```json
{
"小麦": {"花费":120,"收益":100,"品质":"普通"},
"稻谷": {"花费":100,"收益":120,"品质":"普通"}
}
```
## 使用场景
- **标准格式化**: 适合阅读和编辑,开发时使用
- **最小化**: 适合网络传输,节省带宽
- **一行化**: 适合比较不同对象,每行一个对象便于查看差异
## 批量添加属性示例
添加键名: `能否购买`, 键值: `true`
### 结果:
```json
{
"小麦": {
"花费": 120,
"收益": 100,
"品质": "普通",
"能否购买": true
},
"稻谷": {
"花费": 100,
"收益": 120,
"品质": "普通",
"能否购买": true
}
}
```

View File

@@ -0,0 +1,267 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from flask import Flask, request, jsonify, render_template, send_file
import json
import os
from datetime import datetime
app = Flask(__name__)
class JSONFormatter:
"""JSON格式化工具类"""
@staticmethod
def format_standard(data, indent=2):
"""标准格式化 - 带缩进的可读格式"""
return json.dumps(data, ensure_ascii=False, indent=indent)
@staticmethod
def minify(data):
"""最小化 - 压缩去除空格"""
return json.dumps(data, ensure_ascii=False, separators=(',', ':'))
@staticmethod
def one_line_per_object(data):
"""一行化 - 每个对象/元素占一行"""
if isinstance(data, list):
# 如果是数组,每个元素占一行
lines = ['[']
for i, item in enumerate(data):
comma = ',' if i < len(data) - 1 else ''
lines.append(f' {json.dumps(item, ensure_ascii=False)}{comma}')
lines.append(']')
return '\n'.join(lines)
elif isinstance(data, dict):
# 如果是对象,每个键值对占一行
lines = ['{']
keys = list(data.keys())
for i, key in enumerate(keys):
comma = ',' if i < len(keys) - 1 else ''
value_str = json.dumps(data[key], ensure_ascii=False)
lines.append(f' {json.dumps(key, ensure_ascii=False)}: {value_str}{comma}')
lines.append('}')
return '\n'.join(lines)
else:
# 基本类型直接返回
return json.dumps(data, ensure_ascii=False)
@app.route('/')
def index():
"""主页"""
return render_template('json_editor.html')
@app.route('/api/format', methods=['POST'])
def format_json():
"""JSON格式化API"""
try:
data = request.get_json()
content = data.get('content', '')
format_type = data.get('format_type', 'standard') # standard, minify, oneline
if not content.strip():
return jsonify({'success': False, 'message': '请提供JSON内容'})
# 解析JSON
try:
json_data = json.loads(content)
except json.JSONDecodeError as e:
return jsonify({'success': False, 'message': f'JSON格式错误: {str(e)}'})
# 根据类型格式化
formatter = JSONFormatter()
if format_type == 'standard':
formatted = formatter.format_standard(json_data)
message = 'JSON标准格式化完成'
elif format_type == 'minify':
formatted = formatter.minify(json_data)
message = 'JSON最小化完成'
elif format_type == 'oneline':
formatted = formatter.one_line_per_object(json_data)
message = 'JSON一行化格式完成'
else:
return jsonify({'success': False, 'message': '不支持的格式化类型'})
return jsonify({
'success': True,
'message': message,
'formatted': formatted,
'original_length': len(content),
'formatted_length': len(formatted)
})
except Exception as e:
return jsonify({'success': False, 'message': f'处理错误: {str(e)}'})
@app.route('/api/batch_add', methods=['POST'])
def batch_add_property():
"""批量添加属性API"""
try:
data = request.get_json()
content = data.get('content', '')
key_name = data.get('key_name', '')
key_value = data.get('key_value', '')
if not content.strip():
return jsonify({'success': False, 'message': '请提供JSON内容'})
if not key_name.strip():
return jsonify({'success': False, 'message': '请提供键名'})
# 解析JSON
try:
json_data = json.loads(content)
except json.JSONDecodeError as e:
return jsonify({'success': False, 'message': f'JSON格式错误: {str(e)}'})
# 智能解析键值
parsed_value = parse_value(key_value)
# 批量添加属性
count = add_property_to_all_objects(json_data, key_name, parsed_value)
# 格式化输出
formatted = JSONFormatter.format_standard(json_data)
return jsonify({
'success': True,
'message': f'成功为 {count} 个对象添加了属性 "{key_name}": {json.dumps(parsed_value, ensure_ascii=False)}',
'formatted': formatted,
'count': count
})
except Exception as e:
return jsonify({'success': False, 'message': f'处理错误: {str(e)}'})
def parse_value(value_str):
"""智能解析值的类型"""
if value_str == '':
return ''
# null
if value_str.lower() == 'null':
return None
# boolean
if value_str.lower() == 'true':
return True
if value_str.lower() == 'false':
return False
# number
try:
if '.' in value_str:
return float(value_str)
else:
return int(value_str)
except ValueError:
pass
# JSON object or array
if (value_str.startswith('{') and value_str.endswith('}')) or \
(value_str.startswith('[') and value_str.endswith(']')):
try:
return json.loads(value_str)
except json.JSONDecodeError:
pass
# string
return value_str
def add_property_to_all_objects(obj, key, value):
"""递归为所有对象添加属性"""
count = 0
def traverse(current):
nonlocal count
if isinstance(current, dict):
current[key] = value
count += 1
# 继续递归处理嵌套对象
for val in current.values():
if isinstance(val, (dict, list)) and val != current:
traverse(val)
elif isinstance(current, list):
for item in current:
traverse(item)
traverse(obj)
return count
@app.route('/api/validate', methods=['POST'])
def validate_json():
"""JSON验证API"""
try:
data = request.get_json()
content = data.get('content', '')
if not content.strip():
return jsonify({'success': False, 'message': '请提供JSON内容'})
try:
json_data = json.loads(content)
return jsonify({
'success': True,
'message': 'JSON格式正确 ✓',
'valid': True
})
except json.JSONDecodeError as e:
return jsonify({
'success': False,
'message': f'JSON格式错误: {str(e)}',
'valid': False,
'error': str(e)
})
except Exception as e:
return jsonify({'success': False, 'message': f'验证错误: {str(e)}'})
@app.route('/api/download', methods=['POST'])
def download_json():
"""下载JSON文件"""
try:
data = request.get_json()
content = data.get('content', '')
format_type = data.get('format_type', 'standard')
if not content.strip():
return jsonify({'success': False, 'message': '没有可下载的内容'})
# 验证JSON格式
try:
json_data = json.loads(content)
except json.JSONDecodeError as e:
return jsonify({'success': False, 'message': f'JSON格式错误: {str(e)}'})
# 格式化
formatter = JSONFormatter()
if format_type == 'minify':
formatted_content = formatter.minify(json_data)
elif format_type == 'oneline':
formatted_content = formatter.one_line_per_object(json_data)
else:
formatted_content = formatter.format_standard(json_data)
# 生成文件名
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"edited_json_{format_type}_{timestamp}.json"
# 创建临时文件
temp_file = f"temp_{filename}"
with open(temp_file, 'w', encoding='utf-8') as f:
f.write(formatted_content)
return send_file(temp_file, as_attachment=True, download_name=filename)
except Exception as e:
return jsonify({'success': False, 'message': f'下载错误: {str(e)}'})
if __name__ == '__main__':
# 确保templates目录存在
os.makedirs('templates', exist_ok=True)
# 运行应用
app.run(debug=True, host='0.0.0.0', port=5000)

View File

@@ -0,0 +1,2 @@
Flask==2.3.3
Werkzeug==2.3.7

View File

@@ -0,0 +1,627 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简易JSON编辑器 - 批量添加键值</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f5f5;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
overflow: hidden;
}
.header {
background: #4a90e2;
color: white;
padding: 20px;
text-align: center;
}
.header h1 {
margin-bottom: 5px;
}
.main-content {
display: grid;
grid-template-columns: 300px 1fr;
gap: 0;
min-height: 600px;
}
.sidebar {
background: #f8f9fa;
border-right: 1px solid #dee2e6;
padding: 20px;
}
.editor-area {
padding: 20px;
}
.section {
background: white;
border: 1px solid #dee2e6;
border-radius: 5px;
padding: 15px;
margin-bottom: 15px;
}
.section h3 {
margin-bottom: 15px;
color: #333;
}
.btn {
background: #4a90e2;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
margin: 5px 5px 5px 0;
width: 100%;
}
.btn:hover {
background: #357abd;
}
.btn-success {
background: #28a745;
}
.btn-success:hover {
background: #218838;
}
.input-group {
margin-bottom: 15px;
}
.input-group label {
display: block;
margin-bottom: 5px;
font-weight: 500;
color: #333;
}
.input-group input {
width: 100%;
padding: 8px 12px;
border: 1px solid #dee2e6;
border-radius: 5px;
font-size: 14px;
}
.input-group input:focus {
outline: none;
border-color: #4a90e2;
}
#jsonEditor {
width: 100%;
height: 500px;
border: 1px solid #dee2e6;
border-radius: 5px;
padding: 15px;
font-family: 'Courier New', monospace;
font-size: 14px;
line-height: 1.5;
resize: vertical;
}
#jsonEditor:focus {
outline: none;
border-color: #4a90e2;
}
.file-upload {
position: relative;
display: inline-block;
cursor: pointer;
overflow: hidden;
width: 100%;
}
.file-upload input[type=file] {
position: absolute;
left: -9999px;
}
.alert {
padding: 10px 15px;
margin-bottom: 15px;
border-radius: 5px;
font-weight: 500;
}
.alert-success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.alert-error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.alert-info {
background: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
@media (max-width: 768px) {
.main-content {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🔧 JSON批量编辑器</h1>
<p>批量添加键值对到JSON文件</p>
</div>
<div class="main-content">
<!-- 侧边栏 -->
<div class="sidebar">
<!-- 文件操作 -->
<div class="section">
<h3>📁 文件操作</h3>
<div class="file-upload btn">
<input type="file" id="fileInput" accept=".json" />
上传JSON文件
</div>
<button class="btn btn-success" onclick="downloadJSON()">
下载修改后的JSON
</button>
</div>
<!-- 批量添加键值 -->
<div class="section">
<h3>⚡ 批量添加键值</h3>
<div class="input-group">
<label for="keyName">键名:</label>
<input type="text" id="keyName" placeholder="例: 能否购买" />
</div>
<div class="input-group">
<label for="keyValue">键值:</label>
<input type="text" id="keyValue" placeholder="支持多种类型,见下方说明" />
</div>
<button class="btn btn-success" onclick="batchAddProperty()">
批量添加到所有对象
</button>
<div style="margin-top: 15px; padding: 10px; background: #f8f9fa; border-radius: 5px; font-size: 12px;">
<strong>支持的数据类型:</strong><br>
• 字符串: hello world<br>
• 数字: 123 或 3.14<br>
• 布尔值: true 或 false<br>
• 空值: null<br>
• 对象: {"key": "value"}<br>
• 数组: [1, 2, 3]<br>
<small style="color: #666;">系统会自动识别并转换数据类型</small>
</div>
</div>
<!-- 快速示例 -->
<div class="section">
<h3>📝 快速示例</h3>
<button class="btn" onclick="loadSampleJSON()">
加载示例数据
</button>
<div style="margin-top: 15px;">
<strong style="font-size: 12px;">快速填入示例键值:</strong><br>
<button class="btn" style="font-size: 11px; padding: 5px 10px; margin: 2px;" onclick="fillExample('能否购买', 'true')">
布尔值示例
</button>
<button class="btn" style="font-size: 11px; padding: 5px 10px; margin: 2px;" onclick="fillExample('价格', '150')">
数字示例
</button>
<button class="btn" style="font-size: 11px; padding: 5px 10px; margin: 2px;" onclick="fillExample('备注', '新增属性')">
字符串示例
</button>
<button class="btn" style="font-size: 11px; padding: 5px 10px; margin: 2px;" onclick="fillExample('tags', '[&quot;新&quot;, &quot;热门&quot;]')">
数组示例
</button>
</div>
</div>
<!-- JSON格式化操作 -->
<div class="section">
<h3>🔧 格式化操作</h3>
<button class="btn" onclick="formatJSONStandard()">
标准格式化
</button>
<button class="btn btn-success" onclick="minifyJSON()">
最小化(压缩)
</button>
<button class="btn" style="background: #17a2b8;" onclick="oneLinePerObject()">
一行化(一个对象一行)
</button>
<button class="btn" style="background: #6f42c1; color: white;" onclick="validateJSON()">
验证JSON格式
</button>
<div style="margin-top: 15px; padding: 10px; background: #f8f9fa; border-radius: 5px; font-size: 12px;">
<strong>格式化说明:</strong><br>
<strong>标准格式化</strong>: 2空格缩进易于阅读<br>
<strong>最小化</strong>: 去除空格,节省空间<br>
<strong>一行化</strong>: 每个对象占一行,便于比较<br>
<strong>验证格式</strong>: 检查JSON语法是否正确<br>
</div>
</div>
</div>
<!-- 编辑区域 -->
<div class="editor-area">
<!-- 消息区域 -->
<div id="messageArea"></div>
<!-- JSON编辑器 -->
<textarea id="jsonEditor" placeholder="在此输入或上传JSON数据..."></textarea>
</div>
</div>
</div>
<script>
// 初始化
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('fileInput').addEventListener('change', handleFileUpload);
});
// 显示消息
function showMessage(message, type = 'success') {
const messageArea = document.getElementById('messageArea');
let alertClass = 'alert-success';
if (type === 'error') {
alertClass = 'alert-error';
} else if (type === 'info') {
alertClass = 'alert-info';
}
messageArea.innerHTML = `
<div class="alert ${alertClass}">
${message}
</div>
`;
setTimeout(() => {
messageArea.innerHTML = '';
}, 3000);
}
// 加载示例JSON
function loadSampleJSON() {
const sampleJSON = {
"测试作物": {
"花费": 1,
"生长时间": 3,
"收益": 9999,
"品质": "普通"
},
"小麦": {
"花费": 120,
"生长时间": 120,
"收益": 100,
"品质": "普通"
},
"稻谷": {
"花费": 100,
"生长时间": 240,
"收益": 120,
"品质": "普通"
}
};
document.getElementById('jsonEditor').value = JSON.stringify(sampleJSON, null, 2);
showMessage('示例数据已加载');
}
// 快速填入示例键值对
function fillExample(keyName, keyValue) {
document.getElementById('keyName').value = keyName;
document.getElementById('keyValue').value = keyValue;
showMessage(`已填入示例: ${keyName} = ${keyValue}`, 'info');
}
// 文件上传处理
function handleFileUpload(event) {
const file = event.target.files[0];
if (!file) return;
if (!file.name.toLowerCase().endsWith('.json')) {
showMessage('请选择JSON文件', 'error');
return;
}
const reader = new FileReader();
reader.onload = function(e) {
try {
const content = e.target.result;
JSON.parse(content); // 验证JSON格式
document.getElementById('jsonEditor').value = content;
showMessage('文件上传成功');
} catch (error) {
showMessage('JSON格式错误: ' + error.message, 'error');
}
};
reader.readAsText(file);
// 清空文件输入
event.target.value = '';
}
// 批量添加属性
function batchAddProperty() {
const keyName = document.getElementById('keyName').value.trim();
const keyValue = document.getElementById('keyValue').value.trim();
const jsonContent = document.getElementById('jsonEditor').value.trim();
if (!keyName) {
showMessage('请输入键名', 'error');
return;
}
if (!jsonContent) {
showMessage('请输入或上传JSON数据', 'error');
return;
}
try {
let jsonData = JSON.parse(jsonContent);
// 智能类型转换
let processedValue = parseValue(keyValue);
// 批量添加属性
const result = addPropertyToAllObjects(jsonData, keyName, processedValue);
if (result.count > 0) {
document.getElementById('jsonEditor').value = JSON.stringify(jsonData, null, 2);
showMessage(`成功为 ${result.count} 个对象添加了属性 "${keyName}": ${JSON.stringify(processedValue)}`);
} else {
showMessage('未找到可添加属性的对象', 'info');
}
} catch (error) {
showMessage('JSON格式错误: ' + error.message, 'error');
}
}
// 智能解析值的类型
function parseValue(value) {
// 如果输入为空,返回空字符串
if (value === '') {
return '';
}
// 尝试解析为null
if (value.toLowerCase() === 'null') {
return null;
}
// 尝试解析为undefined虽然JSON不支持但转为null
if (value.toLowerCase() === 'undefined') {
return null;
}
// 尝试解析为布尔值
if (value.toLowerCase() === 'true') {
return true;
}
if (value.toLowerCase() === 'false') {
return false;
}
// 尝试解析为数字
if (!isNaN(value) && !isNaN(parseFloat(value))) {
// 检查是否为整数
if (Number.isInteger(parseFloat(value))) {
return parseInt(value, 10);
} else {
return parseFloat(value);
}
}
// 尝试解析为JSON对象或数组
if ((value.startsWith('{') && value.endsWith('}')) ||
(value.startsWith('[') && value.endsWith(']'))) {
try {
return JSON.parse(value);
} catch (e) {
// 如果解析失败,当作字符串处理
return value;
}
}
// 默认当作字符串处理
return value;
}
// 递归为所有对象添加属性
function addPropertyToAllObjects(obj, key, value) {
let count = 0;
function traverse(current) {
if (typeof current === 'object' && current !== null) {
if (Array.isArray(current)) {
// 处理数组
current.forEach(item => traverse(item));
} else {
// 处理对象
current[key] = value;
count++;
// 继续递归处理嵌套对象
Object.values(current).forEach(val => {
if (typeof val === 'object' && val !== null && val !== current) {
traverse(val);
}
});
}
}
}
traverse(obj);
return { count };
}
// 下载JSON
function downloadJSON() {
const content = document.getElementById('jsonEditor').value.trim();
if (!content) {
showMessage('没有可下载的内容', 'error');
return;
}
try {
// 验证JSON格式
JSON.parse(content);
const blob = new Blob([content], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `edited_json_${new Date().getTime()}.json`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
showMessage('JSON文件下载成功');
} catch (error) {
showMessage('JSON格式错误无法下载: ' + error.message, 'error');
}
}
// 标准格式化JSON
function formatJSONStandard() {
const content = document.getElementById('jsonEditor').value.trim();
if (!content) {
showMessage('请输入JSON数据', 'error');
return;
}
try {
const jsonData = JSON.parse(content);
const formatted = JSON.stringify(jsonData, null, 2);
document.getElementById('jsonEditor').value = formatted;
showMessage('JSON标准格式化完成');
} catch (error) {
showMessage('JSON格式错误: ' + error.message, 'error');
}
}
// 最小化JSON压缩
function minifyJSON() {
const content = document.getElementById('jsonEditor').value.trim();
if (!content) {
showMessage('请输入JSON数据', 'error');
return;
}
try {
const jsonData = JSON.parse(content);
const minified = JSON.stringify(jsonData);
document.getElementById('jsonEditor').value = minified;
showMessage('JSON最小化完成');
} catch (error) {
showMessage('JSON格式错误: ' + error.message, 'error');
}
}
// 一行化格式(一个对象一行)
function oneLinePerObject() {
const content = document.getElementById('jsonEditor').value.trim();
if (!content) {
showMessage('请输入JSON数据', 'error');
return;
}
try {
const jsonData = JSON.parse(content);
let formatted = '';
if (Array.isArray(jsonData)) {
// 如果是数组,每个元素占一行
formatted = '[\n';
jsonData.forEach((item, index) => {
formatted += ' ' + JSON.stringify(item);
if (index < jsonData.length - 1) {
formatted += ',';
}
formatted += '\n';
});
formatted += ']';
} else if (typeof jsonData === 'object' && jsonData !== null) {
// 如果是对象,每个键值对占一行
formatted = '{\n';
const keys = Object.keys(jsonData);
keys.forEach((key, index) => {
formatted += ' ' + JSON.stringify(key) + ': ' + JSON.stringify(jsonData[key]);
if (index < keys.length - 1) {
formatted += ',';
}
formatted += '\n';
});
formatted += '}';
} else {
// 基本类型直接输出
formatted = JSON.stringify(jsonData);
}
document.getElementById('jsonEditor').value = formatted;
showMessage('JSON一行化格式完成');
} catch (error) {
showMessage('JSON格式错误: ' + error.message, 'error');
}
}
// 验证JSON格式
function validateJSON() {
const content = document.getElementById('jsonEditor').value.trim();
if (!content) {
showMessage('请输入JSON数据', 'error');
return;
}
try {
JSON.parse(content);
showMessage('JSON格式验证通过');
} catch (error) {
showMessage('JSON格式错误: ' + error.message, 'error');
}
}
</script>
</body>
</html>