using Newtonsoft.Json; namespace etoy { internal class CmdExportJsonDatabase : Command { /// /// 默认: Server /// public TableTag TableTag { get; set; } = TableTag.Server; public override string Description => "导出数据库-JSON"; protected virtual TableTag AllowedTableTag => TableTag; protected virtual KeyValueTag AllowedKeyValueTag { get { return TableTag switch { TableTag.Client => KeyValueTag.Client, TableTag.Server => KeyValueTag.Server, _ => KeyValueTag.All, }; } } protected virtual string DatabaseOutput => TableTag == TableTag.Server ? Context.Option.ServerDatabaseOutput : Context.Option.ClientDatabaseOutput; private readonly string TableExt = ".json"; private readonly List _errors = new List(); protected override void OnProcess() { var outputPath = DatabaseOutput.ToPath(); if (Directory.Exists(outputPath)) Directory.Delete(outputPath, true); Directory.CreateDirectory(outputPath); SetProgress(0.1f); ExportTables(Context, outputPath); if (_errors.Count > 0) { SetException(new Exception(string.Join('\n', (from e in _errors select $"## ERROR: {e.Message}").ToArray()))); } else { Completed(); } } private void ExportTables(Context context, string outputPath) { foreach (var table in Context.Blackboard.Tables) { if (HasTableFlag(table.TableTag)) { try { ExportTable(context, outputPath, table); } catch (Exception ex) { _errors.Add(ex); } } } } private void ExportTable(Context context, string outputPath, Table table) { var fileName = table.Name + TableExt; var filePath = Path.Combine(outputPath, fileName); //var serializables = new List(); using var jsonWriter = new JsonWriter(true); jsonWriter.ArrayBracket().Indent().NewLine(); for (int i = 0, rowCount = table.Rows.Count; i < rowCount; i++) { var row = table.Rows[i]; jsonWriter.Bracket(); //var fieldGroup = new SerializableFieldGroup(); var isFieldFirst = true; for (int j = 0, colCount = row.Cells.Count; j < colCount; j++) { var cell = row.Cells[j]; var fieldInfo = cell.FieldInfo; if (HasTableFlag(fieldInfo.OutputTag) == false) { continue; } if (isFieldFirst) { // 第一个属性前面不用加逗号 isFieldFirst = false; } else { jsonWriter.Dot(); } if (context.Blackboard.TryGetMetadata(fieldInfo.FieldType, out var metadata)) { // 是自定义属性 var cellVal = cell.Value; if (metadata.StructType == MetadataStructType.Enum) {// 枚举 cellVal = SerializeEnum(fieldInfo.FieldType, fieldInfo.FieldName, fieldInfo.IsRepeated, cell.Value, metadata); } //else //{ // 数据结构 // // 自定义的结构体的cell.Value已经是json字符串,直接写入 //} jsonWriter.AppendKey(fieldInfo.FieldName).AppendForce(cellVal); } else { // 普通字段 jsonWriter.AppendKey(fieldInfo.FieldName); if (fieldInfo.IsRepeated || fieldInfo.FieldType != FieldTypeDefine.String) { jsonWriter.AppendForce(cell.Value); } else { jsonWriter.Append(cell.Value); } } } jsonWriter.EndBracket(); if (i < rowCount - 1) { // 最后一行后面不用加逗号 jsonWriter.Dot().NewLine(); } else { jsonWriter.Dedent().NewLine(); } } jsonWriter.EndArrayBracket(); File.WriteAllText(filePath, jsonWriter.Json); } /// /// 序列化枚举的值 /// 转成int或者int[]对应的json字符串 /// /// /// /// /// /// /// private string SerializeEnum(string fieldType, string fieldName, bool isRepeated, string value, MetadataStruct meta) { if (isRepeated) { int[] enumIntVals = null; try { enumIntVals = JsonConvert.DeserializeObject(value); } catch (Exception ex) { Console.WriteLine($"枚举数组转int[]失败 Type:{fieldType} Name:{fieldName} Value:{value} Message:{ex.Message}"); } if (enumIntVals == null) { var enumVals = JsonConvert.DeserializeObject(value); var count = enumVals?.Length ?? 0; enumIntVals = new int[count]; for (int i = 0; i < count; i++) { if (!int.TryParse(enumVals[i], out var intVal)) { // 存的是枚举的名字 var field = meta.Fields.First(a => a.Name.Equals(enumVals[i], StringComparison.OrdinalIgnoreCase)); intVal = field?.EnumIntVal ?? 0; } enumIntVals[i] = intVal; } } return JsonConvert.SerializeObject(enumIntVals); } else { if (!int.TryParse(value, out var intVal)) { // value存的是枚举的名字 var field = meta.Fields.First(a => a.Name.Equals(value, StringComparison.OrdinalIgnoreCase)); intVal = field?.EnumIntVal ?? 0; } return intVal.ToString(); } } private bool HasTableFlag(TableTag tag) { return AllowedTableTag == TableTag.All || tag.HasFlag(AllowedTableTag); } //private bool HasKeyValueFlag(KeyValueTag tag) //{ // return AllowedKeyValueTag == KeyValueTag.All || tag.HasFlag(AllowedKeyValueTag); //} } }