using System.Text; namespace etoy { class CmdKsonToJson : Command { public override string Description => "将Kson数据转成Json"; List _errors = new List(); int _total; int _done; protected override void OnProcess() { _total = Context.Blackboard.Tables.Count; Task.Factory.StartNew(OnThread); Task.Factory.StartNew(() => { while (_done < _total) Thread.Sleep(1); if (_errors.Count > 0) SetException(new Exception(string.Join('\n', (from e in _errors select $"## ERROR: {e.Message}").ToArray()))); else Completed(); }); } private void OnThread() { var tables = Context.Blackboard.Tables; for (int i = 0; i < _total; i++) { var table = tables[i]; SingleTable(table); SetProgress(++_done / (float)_total); } } void SingleTable(Table table) { for (int i = 0, rowCount = table.Rows.Count; i < rowCount; i++) { var row = table.Rows[i]; for (int j = 0, colCount = row.Cells.Count; j < colCount; j++) { var cell = row.Cells[j]; if (Context.Blackboard.TryGetMetadata(cell.FieldInfo.FieldType, out var metadata) && metadata.StructType == MetadataStructType.Struct) { if (cell.Value.IsKsonString()) { string json; string repeated = cell.FieldInfo.IsRepeated ? "[]" : string.Empty; try { json = FromKsonToJson(cell.Value, metadata, cell.FieldInfo.IsRepeated); } catch (Exception e) { _errors.Add(new Exception($"Kson解析失败, {e.Message}。 类型: {cell.FieldInfo.FieldType}{repeated}\n配置表: {table.Name}, 字段: {cell.FieldInfo.FieldName}, kson: {cell.Value}\n")); continue; } if (!json.IsJsonString()) { _errors.Add(new Exception($"kson转出来的json不合法, kson: {cell.Value}, json: {json}, Table: {table.Name}, Field: {cell.FieldInfo.FieldName}, FieldType: {cell.FieldInfo.FieldType}{repeated}")); continue; } // 正确才改值 cell.Value = json; } } } } } string FromKsonToJson(string kson, MetadataStruct metadata, bool isRepeated) { StringBuilder sb = new StringBuilder(); KsonObject ksonObject = new KsonObject(kson); if (ksonObject.IsArray != isRepeated || ksonObject.IsObject == isRepeated) throw new Exception("Kson配置错误"); if (ksonObject.IsObject) { ToObjectJson(sb, ksonObject, metadata, string.Empty); } else { sb.Append("["); for (int i = 0, length = ksonObject.ArrayObjects.Count; i < length; i++) { var list = ksonObject.ArrayObjects[i]; for (int j = 0, count = list.Count; j < count; j++) { ToObjectJson(sb, list[j], metadata, string.Empty); if (j < count - 1) sb.Append(","); } if (i < length - 1) sb.Append(","); } sb.Append("]"); } return sb.ToString(); } void ToObjectJson(StringBuilder sb, KsonObject ksonObject, MetadataStruct metadata, string key) { key = string.IsNullOrEmpty(key) ? "{" : $"\"{key}\":{{"; sb.Append(key); // 0允许, 即{}. 非0且数量不相等便是策划配置字段数量有误 int fieldCount = ksonObject.FieldCount; if (fieldCount != 0 && fieldCount != metadata.Fields.Length) throw new Exception("字段数量不一致"); for (int i = 0; i < fieldCount; i++) { var field = metadata.Fields[i]; var fieldName = field.Name; var fieldType = field.FieldType; if (Context.Blackboard.TryGetMetadata(fieldType, out var fieldMetadata)) { if (ksonObject.KsonObjects.TryGetValue(i, out var obj)) { ToObjectJson(sb, obj, fieldMetadata, fieldName); } else if (ksonObject.ArrayObjects.TryGetValue(i, out var array)) { sb.Append($"\"{fieldName}\":["); for (int j = 0, arrayCount = array.Count; j < arrayCount; j++) { ToObjectJson(sb, array[j], fieldMetadata, string.Empty); if (j < arrayCount - 1) sb.Append(","); } sb.Append("]"); } } else if (ksonObject.StringValues.TryGetValue(i, out var stringValue)) { switch (fieldType) { case FieldTypeDefine.Boolean: case FieldTypeDefine.Int: case FieldTypeDefine.Long: case FieldTypeDefine.Float: case FieldTypeDefine.Double: sb.Append($"\"{fieldName}\":{stringValue}"); break; default: sb.Append($"\"{fieldName}\":\"{stringValue}\""); break; } } else if (ksonObject.ArrayObjects.TryGetValue(i, out var array)) { sb.Append($"\"{fieldName}\":["); for (int j = 0, arrayCount = array.Count; j < arrayCount; j++) { var item = array[j]; switch (fieldType) { case FieldTypeDefine.Boolean: case FieldTypeDefine.Int: case FieldTypeDefine.Long: case FieldTypeDefine.Float: case FieldTypeDefine.Double: sb.Append(item.RawKson); break; default: sb.Append($"\"{item.RawKson}\""); break; } if (j < arrayCount - 1) sb.Append(","); } sb.Append("]"); } if (i < fieldCount - 1) sb.Append(","); } sb.Append("}"); } } }