289 lines
8.6 KiB
TypeScript
289 lines
8.6 KiB
TypeScript
import { invoke } from '@tauri-apps/api/core';
|
||
|
||
export interface ParseJsonRequest {
|
||
text: string;
|
||
config?: JsonParserConfig;
|
||
}
|
||
|
||
export interface JsonParserConfig {
|
||
max_text_length?: number;
|
||
enable_comments?: boolean;
|
||
enable_unquoted_keys?: boolean;
|
||
enable_trailing_commas?: boolean;
|
||
timeout_ms?: number;
|
||
recovery_strategies?: string[];
|
||
}
|
||
|
||
export interface ParseStatistics {
|
||
total_nodes: number;
|
||
error_nodes: number;
|
||
error_rate: number;
|
||
parse_time_ms: number;
|
||
recovery_strategies_used: string[];
|
||
}
|
||
|
||
export interface ParseJsonResponse {
|
||
success: boolean;
|
||
data?: any;
|
||
statistics?: ParseStatistics;
|
||
error?: string;
|
||
}
|
||
|
||
/**
|
||
* 容错JSON解析服务
|
||
* 提供与后端JSON解析器的交互接口
|
||
*/
|
||
export class TolerantJsonService {
|
||
/**
|
||
* 解析JSON文本
|
||
*/
|
||
static async parseJson(request: ParseJsonRequest): Promise<ParseJsonResponse> {
|
||
try {
|
||
const response = await invoke<ParseJsonResponse>('parse_json_tolerant', { request });
|
||
return response;
|
||
} catch (error) {
|
||
throw new Error(`JSON解析失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 验证JSON格式
|
||
*/
|
||
static async validateJson(text: string): Promise<boolean> {
|
||
try {
|
||
return await invoke<boolean>('validate_json_format', { text });
|
||
} catch (error) {
|
||
throw new Error(`JSON验证失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 格式化JSON文本
|
||
*/
|
||
static async formatJson(text: string, indent: number = 2): Promise<string> {
|
||
try {
|
||
return await invoke<string>('format_json_text', { text, indent });
|
||
} catch (error) {
|
||
throw new Error(`JSON格式化失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取支持的恢复策略列表
|
||
*/
|
||
static async getRecoveryStrategies(): Promise<string[]> {
|
||
try {
|
||
return await invoke<string[]>('get_recovery_strategies');
|
||
} catch (error) {
|
||
throw new Error(`获取恢复策略失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取默认解析器配置
|
||
*/
|
||
static async getDefaultConfig(): Promise<JsonParserConfig> {
|
||
try {
|
||
return await invoke<JsonParserConfig>('get_default_parser_config');
|
||
} catch (error) {
|
||
throw new Error(`获取默认配置失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 批量解析JSON文本
|
||
*/
|
||
static async batchParseJson(
|
||
texts: string[],
|
||
config?: JsonParserConfig,
|
||
onProgress?: (current: number, total: number) => void
|
||
): Promise<ParseJsonResponse[]> {
|
||
const results: ParseJsonResponse[] = [];
|
||
|
||
for (let i = 0; i < texts.length; i++) {
|
||
try {
|
||
const result = await this.parseJson({ text: texts[i], config });
|
||
results.push(result);
|
||
onProgress?.(i + 1, texts.length);
|
||
} catch (error) {
|
||
results.push({
|
||
success: false,
|
||
error: error instanceof Error ? error.message : '解析失败'
|
||
});
|
||
onProgress?.(i + 1, texts.length);
|
||
}
|
||
}
|
||
|
||
return results;
|
||
}
|
||
|
||
/**
|
||
* 预设配置
|
||
*/
|
||
static getPresetConfigs(): Record<string, JsonParserConfig> {
|
||
return {
|
||
// 严格模式 - 只使用标准JSON解析
|
||
strict: {
|
||
max_text_length: 1024 * 1024,
|
||
enable_comments: false,
|
||
enable_unquoted_keys: false,
|
||
enable_trailing_commas: false,
|
||
timeout_ms: 10000,
|
||
recovery_strategies: ['StandardJson']
|
||
},
|
||
|
||
// 宽松模式 - 启用所有容错功能
|
||
lenient: {
|
||
max_text_length: 1024 * 1024,
|
||
enable_comments: true,
|
||
enable_unquoted_keys: true,
|
||
enable_trailing_commas: true,
|
||
timeout_ms: 30000,
|
||
recovery_strategies: ['StandardJson', 'ManualFix', 'RegexExtract', 'PartialParse']
|
||
},
|
||
|
||
// AI模式 - 专门处理AI模型返回的数据
|
||
ai_model: {
|
||
max_text_length: 2 * 1024 * 1024, // 2MB
|
||
enable_comments: true,
|
||
enable_unquoted_keys: true,
|
||
enable_trailing_commas: true,
|
||
timeout_ms: 60000, // 1分钟
|
||
recovery_strategies: ['ManualFix', 'RegexExtract', 'PartialParse', 'StandardJson']
|
||
},
|
||
|
||
// 快速模式 - 优先性能
|
||
fast: {
|
||
max_text_length: 512 * 1024, // 512KB
|
||
enable_comments: false,
|
||
enable_unquoted_keys: true,
|
||
enable_trailing_commas: true,
|
||
timeout_ms: 5000,
|
||
recovery_strategies: ['StandardJson', 'ManualFix']
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 获取错误恢复策略的描述
|
||
*/
|
||
static getStrategyDescriptions(): Record<string, string> {
|
||
return {
|
||
'StandardJson': '标准JSON解析 - 使用原生JSON.parse()',
|
||
'YamlStringParsing': 'YAML智能解析 - 自动识别并解析字符串中的YAML内容',
|
||
'ManualFix': '手动修复 - 自动修复常见格式错误',
|
||
'RegexExtract': '正则提取 - 使用正则表达式提取JSON片段',
|
||
'PartialParse': '部分解析 - 尝试解析部分有效的JSON内容'
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 分析解析统计信息
|
||
*/
|
||
static analyzeStatistics(stats: ParseStatistics): {
|
||
quality: 'excellent' | 'good' | 'fair' | 'poor';
|
||
recommendations: string[];
|
||
} {
|
||
const { error_rate, parse_time_ms, recovery_strategies_used } = stats;
|
||
|
||
let quality: 'excellent' | 'good' | 'fair' | 'poor';
|
||
const recommendations: string[] = [];
|
||
|
||
// 根据错误率判断质量
|
||
if (error_rate === 0) {
|
||
quality = 'excellent';
|
||
} else if (error_rate < 0.1) {
|
||
quality = 'good';
|
||
} else if (error_rate < 0.3) {
|
||
quality = 'fair';
|
||
recommendations.push('建议检查JSON格式,存在较多语法错误');
|
||
} else {
|
||
quality = 'poor';
|
||
recommendations.push('JSON格式存在严重问题,建议手动检查和修复');
|
||
}
|
||
|
||
// 根据解析时间给出建议
|
||
if (parse_time_ms > 1000) {
|
||
recommendations.push('解析时间较长,建议减少文本长度或简化JSON结构');
|
||
}
|
||
|
||
// 根据使用的恢复策略给出建议
|
||
if (recovery_strategies_used.includes('PartialParse')) {
|
||
recommendations.push('使用了部分解析,可能存在数据不完整的情况');
|
||
}
|
||
|
||
if (recovery_strategies_used.includes('RegexExtract')) {
|
||
recommendations.push('使用了正则提取,建议检查提取的内容是否完整');
|
||
}
|
||
|
||
if (recovery_strategies_used.length === 0) {
|
||
recommendations.push('JSON格式标准,无需额外处理');
|
||
}
|
||
|
||
return { quality, recommendations };
|
||
}
|
||
|
||
/**
|
||
* 生成解析报告
|
||
*/
|
||
static generateReport(
|
||
input: string,
|
||
result: ParseJsonResponse,
|
||
config: JsonParserConfig
|
||
): string {
|
||
const lines: string[] = [];
|
||
|
||
lines.push('# JSON解析报告');
|
||
lines.push('');
|
||
lines.push(`**解析时间**: ${new Date().toLocaleString()}`);
|
||
lines.push(`**输入长度**: ${input.length} 字符`);
|
||
lines.push(`**解析状态**: ${result.success ? '成功' : '失败'}`);
|
||
lines.push('');
|
||
|
||
if (result.success && result.statistics) {
|
||
const stats = result.statistics;
|
||
const analysis = this.analyzeStatistics(stats);
|
||
|
||
lines.push('## 统计信息');
|
||
lines.push(`- 解析时间: ${stats.parse_time_ms}ms`);
|
||
lines.push(`- 错误率: ${(stats.error_rate * 100).toFixed(2)}%`);
|
||
lines.push(`- 总节点数: ${stats.total_nodes}`);
|
||
lines.push(`- 错误节点数: ${stats.error_nodes}`);
|
||
lines.push(`- 数据质量: ${analysis.quality}`);
|
||
lines.push('');
|
||
|
||
if (stats.recovery_strategies_used.length > 0) {
|
||
lines.push('## 使用的恢复策略');
|
||
stats.recovery_strategies_used.forEach(strategy => {
|
||
const description = this.getStrategyDescriptions()[strategy] || strategy;
|
||
lines.push(`- ${description}`);
|
||
});
|
||
lines.push('');
|
||
}
|
||
|
||
if (analysis.recommendations.length > 0) {
|
||
lines.push('## 建议');
|
||
analysis.recommendations.forEach(rec => {
|
||
lines.push(`- ${rec}`);
|
||
});
|
||
lines.push('');
|
||
}
|
||
} else if (result.error) {
|
||
lines.push('## 错误信息');
|
||
lines.push(result.error);
|
||
lines.push('');
|
||
}
|
||
|
||
lines.push('## 配置信息');
|
||
lines.push(`- 最大文本长度: ${config.max_text_length || 'N/A'}`);
|
||
lines.push(`- 支持注释: ${config.enable_comments ? '是' : '否'}`);
|
||
lines.push(`- 无引号键: ${config.enable_unquoted_keys ? '是' : '否'}`);
|
||
lines.push(`- 尾随逗号: ${config.enable_trailing_commas ? '是' : '否'}`);
|
||
lines.push(`- 超时时间: ${config.timeout_ms || 'N/A'}ms`);
|
||
|
||
return lines.join('\n');
|
||
}
|
||
}
|
||
|
||
export default TolerantJsonService;
|