using System.Globalization; using System.Text.Json; namespace Tnsu.ApprovalRoute.Application.Reports; /// /// Чтение полей из ответа SharePoint REST. Те же грабли, что разобраны в /// Reminders/ApprovalRow: Number-колонка приходит дробной («1.0»), и обычный /// TryGetInt32 на ней возвращает false, а часть полей SharePoint отдаёт строками. /// internal static class SharePointJson { public static string? String(JsonElement e, string name) => e.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String ? v.GetString() is { Length: > 0 } s ? s : null : null; public static int? Int(JsonElement e, string name) { if (!e.TryGetProperty(name, out var v)) return null; if (v.ValueKind == JsonValueKind.Number) { if (v.TryGetInt32(out var i)) return i; return v.TryGetDouble(out var d) && d is >= int.MinValue and <= int.MaxValue ? (int)Math.Round(d) : null; } if (v.ValueKind != JsonValueKind.String) return null; return double.TryParse(v.GetString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var parsed) && parsed is >= int.MinValue and <= int.MaxValue ? (int)Math.Round(parsed) : null; } /// /// Дата БЕЗ приведения к другой зоне: колонки отчёта — dateOnly, SharePoint /// отдаёт их полуночью, и любой сдвиг зоны увёл бы день на соседний. /// public static DateOnly? Date(JsonElement e, string name) => e.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String && DateTimeOffset.TryParse(v.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.None, out var parsed) ? DateOnly.FromDateTime(parsed.DateTime) : null; /// Title развёрнутого персонального поля (…/Title через $expand). null — поле пустое. public static string? PersonTitle(JsonElement e, string name) => e.TryGetProperty(name, out var person) && person.ValueKind == JsonValueKind.Object ? String(person, "Title") : null; }