feat: 实现字典管理后端
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
using System.Text.Json;
|
||||
using TakeoutSaaS.Application.Dictionary.Abstractions;
|
||||
using TakeoutSaaS.Application.Dictionary.Models;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.Dictionary.ImportExport;
|
||||
|
||||
/// <summary>
|
||||
/// JSON 字典导入解析器。
|
||||
/// </summary>
|
||||
public sealed class JsonDictionaryParser : IJsonDictionaryParser
|
||||
{
|
||||
private static readonly JsonDocumentOptions DocumentOptions = new()
|
||||
{
|
||||
AllowTrailingCommas = true
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<DictionaryImportRow>> ParseAsync(Stream stream, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(stream);
|
||||
|
||||
if (stream.CanSeek)
|
||||
{
|
||||
stream.Position = 0;
|
||||
}
|
||||
|
||||
using var document = await JsonDocument.ParseAsync(stream, DocumentOptions, cancellationToken);
|
||||
if (document.RootElement.ValueKind != JsonValueKind.Array)
|
||||
{
|
||||
return Array.Empty<DictionaryImportRow>();
|
||||
}
|
||||
|
||||
var rows = new List<DictionaryImportRow>();
|
||||
var index = 0;
|
||||
|
||||
foreach (var element in document.RootElement.EnumerateArray())
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
index++;
|
||||
|
||||
rows.Add(new DictionaryImportRow
|
||||
{
|
||||
RowNumber = index,
|
||||
Code = ReadString(element, "code"),
|
||||
Key = ReadString(element, "key"),
|
||||
Value = ReadValue(element, "value"),
|
||||
SortOrder = ReadInt(element, "sortOrder"),
|
||||
IsEnabled = ReadBool(element, "isEnabled"),
|
||||
Description = ReadString(element, "description"),
|
||||
Source = ReadString(element, "source")
|
||||
});
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
private static string? ReadString(JsonElement element, string propertyName)
|
||||
{
|
||||
if (!TryGetProperty(element, propertyName, out var value) || value.ValueKind == JsonValueKind.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return value.ValueKind == JsonValueKind.String ? value.GetString() : value.GetRawText();
|
||||
}
|
||||
|
||||
private static string? ReadValue(JsonElement element, string propertyName)
|
||||
{
|
||||
if (!TryGetProperty(element, propertyName, out var value) || value.ValueKind == JsonValueKind.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return value.ValueKind == JsonValueKind.String ? value.GetString() : value.GetRawText();
|
||||
}
|
||||
|
||||
private static int? ReadInt(JsonElement element, string propertyName)
|
||||
{
|
||||
if (!TryGetProperty(element, propertyName, out var value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value.ValueKind == JsonValueKind.Number && value.TryGetInt32(out var number))
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
if (value.ValueKind == JsonValueKind.String && int.TryParse(value.GetString(), out var parsed))
|
||||
{
|
||||
return parsed;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool? ReadBool(JsonElement element, string propertyName)
|
||||
{
|
||||
if (!TryGetProperty(element, propertyName, out var value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value.ValueKind == JsonValueKind.True || value.ValueKind == JsonValueKind.False)
|
||||
{
|
||||
return value.GetBoolean();
|
||||
}
|
||||
|
||||
if (value.ValueKind == JsonValueKind.String && bool.TryParse(value.GetString(), out var parsed))
|
||||
{
|
||||
return parsed;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool TryGetProperty(JsonElement element, string propertyName, out JsonElement value)
|
||||
{
|
||||
foreach (var property in element.EnumerateObject())
|
||||
{
|
||||
if (string.Equals(property.Name, propertyName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
value = property.Value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user