using System.Text.Json; using TakeoutSaaS.Application.Dictionary.Abstractions; using TakeoutSaaS.Application.Dictionary.Models; namespace TakeoutSaaS.Infrastructure.Dictionary.ImportExport; /// /// JSON 字典导入解析器。 /// public sealed class JsonDictionaryParser : IJsonDictionaryParser { private static readonly JsonDocumentOptions DocumentOptions = new() { AllowTrailingCommas = true }; /// public async Task> 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(); } var rows = new List(); 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; } }