Files
TakeoutSaaS.TenantApi/src/Infrastructure/TakeoutSaaS.Infrastructure/Dictionary/ImportExport/JsonDictionaryParser.cs

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