using System.Text.Json; using System.Text.Json.Serialization; namespace MetaforceInstaller.Cloud.Implementations.MailRu.DTO; public sealed class CloudObjectsResponse { [JsonPropertyName("count")] public CountInfo? Count { get; init; } [JsonPropertyName("name")] public string? Name { get; init; } [JsonPropertyName("weblink")] public string? WebLink { get; init; } [JsonPropertyName("size")] public long? Size { get; init; } [JsonPropertyName("rev")] public long? Rev { get; init; } [JsonPropertyName("kind")] public string? Kind { get; init; } [JsonPropertyName("type")] public string? Type { get; init; } [JsonPropertyName("public")] public PublicInfo? Public { get; init; } [JsonPropertyName("list")] public List? List { get; init; } [JsonPropertyName("owner")] public OwnerInfo? Owner { get; init; } } public sealed class CountInfo { [JsonPropertyName("folders")] public int? Folders { get; init; } [JsonPropertyName("files")] public int? Files { get; init; } } public sealed class PublicInfo { [JsonPropertyName("type")] public string? Type { get; init; } [JsonPropertyName("name")] public string? Name { get; init; } [JsonPropertyName("id")] public string? Id { get; init; } [JsonPropertyName("ctime")] public long? CTime { get; init; } [JsonPropertyName("views")] public long? Views { get; init; } [JsonPropertyName("downloads")] public long? Downloads { get; init; } } public sealed class OwnerInfo { [JsonPropertyName("email")] public string? Email { get; init; } [JsonPropertyName("user_flags")] public UserFlags? UserFlags { get; init; } } public sealed class UserFlags { [JsonPropertyName("PAID_ACCOUNT")] public bool? PaidAccount { get; init; } } /// /// Базовый тип элемента из "list". Конкретный тип выбирается по полю "type". /// [JsonConverter(typeof(CloudObjectJsonConverter))] public abstract class CloudObjectBase { [JsonPropertyName("name")] public string? Name { get; init; } [JsonPropertyName("weblink")] public string? WebLink { get; init; } [JsonPropertyName("size")] public long? Size { get; init; } [JsonPropertyName("kind")] public string? Kind { get; init; } [JsonPropertyName("type")] public string? Type { get; init; } } public sealed class CloudFolderObject : CloudObjectBase { [JsonPropertyName("count")] public CountInfo? Count { get; init; } [JsonPropertyName("rev")] public long? Rev { get; init; } } public sealed class CloudFileObject : CloudObjectBase { [JsonPropertyName("mtime")] public long? MTime { get; init; } [JsonPropertyName("hash")] public string? Hash { get; init; } } public sealed class ZipWebLinkRequest { [JsonPropertyName("x-email")] public string XEmail { get; init; } [JsonPropertyName("weblink_list")] public IReadOnlyList WeblinkList { get; init; } [JsonPropertyName("name")] public string Name { get; init; } } public sealed class ZipWebLinkResponse { [JsonPropertyName("key")] public string Key { get; init; } } /// /// Конвертер, который смотрит на поле "type" и десериализует в CloudFolderObject или CloudFileObject. /// public sealed class CloudObjectJsonConverter : JsonConverter { public override CloudObjectBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var doc = JsonDocument.ParseValue(ref reader); var root = doc.RootElement; if (!root.TryGetProperty("type", out var typeProp)) throw new JsonException("Missing required property 'type' for cloud object."); var type = typeProp.GetString(); return type switch { "folder" => root.Deserialize(options) ?? throw new JsonException("Failed to deserialize folder object."), "file" => root.Deserialize(options) ?? throw new JsonException("Failed to deserialize file object."), _ => throw new JsonException($"Unknown cloud object type '{type}'.") }; } public override void Write(Utf8JsonWriter writer, CloudObjectBase value, JsonSerializerOptions options) { switch (value) { case CloudFolderObject folder: JsonSerializer.Serialize(writer, folder, options); break; case CloudFileObject file: JsonSerializer.Serialize(writer, file, options); break; default: throw new JsonException($"Unknown runtime type '{value.GetType().Name}'."); } } }