# aardio 范例: JSON / URL 编码 / aardio（ table ） 格式互转工具



```aardio
//JSON / URL 编码 / table 互转工具
import win.ui;
import fonts.fontAwesome;
/*DSG{{*/
var winform = win.form(text="JSON / URL 编码 / aardio（ table ） 格式互转工具";right=969;bottom=660)
winform.add(
btnHelp={cls="plus";text='\uF02D JSON';left=17;top=617;right=77;bottom=640;db=1;dl=1;font=LOGFONT(h=-13;name='FontAwesome');notify=1;z=12};
btnToJson={cls="plus";text='\uF061 JSON';left=771;top=612;right=860;bottom=643;db=1;dr=1;font=LOGFONT(h=-13;name='FontAwesome');notify=1;z=10};
btnToTable={cls="plus";text='\uF061 table';left=666;top=612;right=763;bottom=643;db=1;dr=1;font=LOGFONT(h=-13;name='FontAwesome');notify=1;z=9};
btnToUrl={cls="plus";text='\uF061 URL';left=868;top=612;right=957;bottom=643;db=1;dr=1;font=LOGFONT(h=-13;name='FontAwesome');notify=1;z=11};
edit={cls="edit";left=11;top=10;right=961;bottom=606;db=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(h=-14;name='Consolas');hscroll=1;multiline=1;vscroll=1;z=1};
lblDetected={cls="static";left=512;top=619;right=600;bottom=641;db=1;dr=1;transparent=1;z=4};
lblFrom={cls="static";text="源格式:";left=61;top=617;right=131;bottom=639;align="right";db=1;dl=1;transparent=1;z=2};
lblTo={cls="static";text="转换为：";left=584;top=619;right=672;bottom=641;align="right";db=1;dr=1;transparent=1;z=8};
radioAuto={cls="radiobutton";text="自动识别";left=423;top=616;right=502;bottom=639;checked=1;db=1;dl=1;z=3};
radioJson={cls="radiobutton";text="JSON";left=243;top=616;right=303;bottom=639;db=1;dl=1;z=6};
radioTable={cls="radiobutton";text="aardio(table)";left=140;top=616;right=242;bottom=639;db=1;dl=1;z=5};
radioUrl={cls="radiobutton";text="URL/URLEncode";left=308;top=616;right=420;bottom=639;db=1;dl=1;z=7}
)
/*}}*/

import JSON;
import util.table;
import inet.url;
import string.curlParse;

winform.edit.limit = -1;

// 当前自动检测到的类型
var currentDetectedType = null;

// 自动识别内容类型
var detectType = function(text){
	text = string.trim(text);
	if(!#text) return null;

	if( (string.find(text,"^[a-zA-Z0-9+/][a-zA-Z0-9+/=]*$")) && (#text%4===0) ){
		import crypt;
		text = ..crypt.decodeBin(text);
		winform.edit.text = text; 
	}
	
	if(string.curlParse.test(text)){
		return "cURL", string.curlParse(text);
	}
	
	// 先检测是否是完整 URL（使用 inet.url.split 准确判断）
	var tUrl = !..string.find(text,'[\r\n]') && inet.url.split(text);
	if(tUrl){
		return "URL", tUrl;
	}
	
	// 检测是否是 URL 参数格式（无换行，有 = 号）
	if(!string.find(text, "\n") && string.indexOf(text, "=") && !string.find(text,"^\s*[\[\{""'`]]")){
		var info = inet.url.splitParametersCs(text);
		if(info && table.count(info) > 0){
			return "URLPARAMS", info;
		}
	}
	
	// 检测是否是 JSON
	var json = JSON.tryParse(text);
	if(json){
		return "JSON", json;
	}
	
	// 尝试作为 table 解析
	var ok,info = call(eval,,text);
	if(ok && type(info) == "table"){
		return "TABLE", info;
	}
	
	return null;
}

// 更新检测结果显示
var updateDetectedLabel = function(dataType){
	select(dataType) {
		case "cURL" {
			winform.lblDetected.text = "(cURL命令)";
		}
		case "URL" {
			winform.lblDetected.text = "(URL)";
		}
		case "URLPARAMS" {
			winform.lblDetected.text = "(URL参数)";
		}
		case "JSON" {
			winform.lblDetected.text = "(JSON)";
		}
		case "TABLE" {
			winform.lblDetected.text = "(table)";
		}
		case "Base64" {
			winform.lblDetected.text = "(Base64)";
		}
		else {
			winform.lblDetected.text = "";
		}
	}
}

// 内容变化时自动检测类型（仅自动识别模式）
winform.edit.onChange = function(){
	if(!winform.radioAuto.checked){
		winform.lblDetected.text = "";
		currentDetectedType = null;
		return;
	}
	
	var dataType = detectType(winform.edit.text);
	currentDetectedType = dataType;
	updateDetectedLabel(dataType);
}

// 其他 radio 点击时清空检测结果
winform.radioTable.oncommand = function(){
	winform.lblDetected.text = "";
	currentDetectedType = null;
}

winform.radioJson.oncommand = function(){
	winform.lblDetected.text = "";
	currentDetectedType = null;
}

winform.radioUrl.oncommand = function(){
	winform.lblDetected.text = "";
	currentDetectedType = null;
}

winform.radioAuto.oncommand = function(){
	// 切换到自动识别时立即检测
	winform.edit.onChange();
}

// 获取当前源类型
var getSourceType = function(){
	if(winform.radioAuto.checked){
		return currentDetectedType;
	}
	if(winform.radioTable.checked) return "TABLE";
	if(winform.radioJson.checked) return "JSON";
	if(winform.radioUrl.checked) return "URL";
	return null;
}

// 解析当前内容
var parseContent = function(){
	var text = string.trim(winform.edit.text);
	if(!#text) return;
	
	var sourceType = getSourceType(); 

	// 自动识别模式，直接检测
	if(!sourceType || sourceType == "AUTO"){
		var dataType, info = detectType(text);
		return info;
	}
	
	if(sourceType == "cURL"){
		if(string.curlParse.test(text)){
			return string.curlParse(text);
		}
	}
	
	if(sourceType == "URL" || sourceType == "URLPARAMS"){
		if(string.curlParse.test(text)){
			return string.curlParse(text);
		}
		
		// 先尝试完整 URL
		var tUrl = inet.url.split(text);
		if(tUrl){
			if(tUrl.extraInfo){
				tUrl.extraInfo = inet.url.splitParametersCs(tUrl.extraInfo);
			}
			
			if(tUrl.path) tUrl.path =..inet.url.decode(tUrl.path);
			return tUrl;
		}
		// 尝试 URL 参数
		return inet.url.splitParametersCs(text);
	}
	
	if(sourceType == "JSON"){
		var data = JSON.tryParse(text);
		if(data){
			if(data[["error"]]){
				table.mapDeep(data,function(v,k,result){
					if(k==="messsage" && type(v)==="string"){
						var msg = ..JSON.tryParse(v);
						if(msg && type(msg)==="table"){
							return msg;
						}
					}
				})
			}
			return data;
		}
	}
	
	if(sourceType == "TABLE"){
		var info = eval(text);
		if(type(info) == "table"){
			return info;
		}
	}
	
	return null;
}

// 判断表是否是 URL 对象（由 inet.url.split 生成）
var isUrlObject = function(tab){
	return type(tab) == "table" && tab.scheme && tab.host && tab.port && (tab.schemeNum!==null);
}

// 转换为 table
winform.btnToTable.oncommand = function(){
	var text = string.trim(winform.edit.text);
	if(!#text){
		winform.edit.showWarningTip("提示", "请输入内容");
		return;
	}
	
	var info = parseContent();
	if(!info){
		winform.edit.showErrorTip("错误", "解析失败，请检查内容格式或手动选择格式");
		return;
	}
	
	winform.edit.text = util.table.tostring(info, '\t');
	winform.radioTable.click();
	winform.lblDetected.text = "";
	currentDetectedType = null;
}

// 转换为 JSON
winform.btnToJson.oncommand = function(){
	var text = string.trim(winform.edit.text);
	if(!#text){
		winform.edit.showWarningTip("提示", "请输入内容");
		return;
	}
	
	var info = parseContent();
	if(!info){
		winform.edit.showErrorTip("错误", "解析失败，请检查内容格式或手动选择格式");
		return;
	}
	
	winform.edit.text = JSON.stringify(info, true, false);
	winform.radioJson.click();
	winform.lblDetected.text = "";
	currentDetectedType = null;
}

// 转换为 URL
winform.btnToUrl.oncommand = function(){
	var text = string.trim(winform.edit.text);
	if(!#text){
		winform.edit.showWarningTip("提示", "请输入内容");
		return;
	}
	
	var info = parseContent();
	if(!info){
		winform.edit.showErrorTip("错误", "解析失败，请检查内容格式或手动选择格式");
		return;
	}
	
	// 如果是 URL 对象（有 scheme,host,port 字段），还原为完整 URL
	if(isUrlObject(info)){
		var tUrl = inet.url.split(info);
		if(tUrl.path)tUrl.path = ..inet.url.encodeUri(tUrl.path);
		winform.edit.text = tostring(tUrl);
	} else {
		// 普通表，转为 URL 参数格式
		winform.edit.text = inet.url.stringifyParameters(info);
	}
	winform.radioUrl.click();
	winform.lblDetected.text = "";
	currentDetectedType = null;
}

winform.btnHelp.oncommand = function(){
	import ide;
	ide.openDocument("https://www.aardio.com/zh-cn/docs/library-guide/std/JSON/_.html")
	winform.show(6/*_SW_MINIMIZE*/);
}

// 设置转换按钮样式
var convertBtnSkin = {
	background = {
		default = 0xFFE0EEFF;
		hover = 0xFFC8DEFF;
		active = 0xFFB0CCEE;
	};
	color = {
		default = 0xFF1E5AAA;
		hover = 0xFF0D4A9A;
		active = 0xFF003A8A;
	};
	border = {
		default = 0xFF7EAEE8;
		hover = 0xFF4E8ED8;
		active = 0xFF2E6EB8;
		radius = 4;
	};
}

winform.btnToTable.skin(convertBtnSkin);
winform.btnToJson.skin(convertBtnSkin);
winform.btnToUrl.skin(convertBtnSkin);

// 设置帮助按钮样式
var helpBtnSkin = {
	background = {
		default = 0xFFF5F5F5;
		hover = 0xFFE8F0FF;
		active = 0xFFD8E4F8;
	};
	color = {
		default = 0xFF0066AA;
		hover = 0xFF0055AA;
		active = 0xFF004499;
	};
	border = {
		default = 0xFFCCCCCC;
		hover = 0xFF88AAD0;
		radius = 3;
	};
}

winform.btnHelp.skin(helpBtnSkin); 

winform.show();
win.loopMessage();
```

