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);
//}
}
}