132 lines
3.8 KiB
C#
132 lines
3.8 KiB
C#
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;
|
|
}
|
|
}
|