/// <summary>
        /// Выполняет "умную" сериализацию в JSON (с учетом настроек протокола).
        /// </summary>
        /// <typeparam name="TValue">Тип сериализуемого объекта.</typeparam>
        /// <param name="value">Сериализуемый объект.</param>
        /// <param name="protocolSettings">Настройки протокола.</param>
        /// <param name="jsonSerializerOptions">Настройки сериализатора.</param>
        /// <returns>JSON-строка сериализованного объекта.</returns>
        public static string SerializeJson <TValue>(TValue value, ProtocolSettings protocolSettings, JsonSerializerOptions jsonSerializerOptions)
        {
            value            = value ?? throw new ArgumentNullException(nameof(value));
            protocolSettings = protocolSettings ?? throw new ArgumentNullException(nameof(protocolSettings));

            string text;

            if (typeof(TValue) == typeof(GetProgramsResponse) && protocolSettings.SingularGetProgramsResponse)
            {
                var helper = new Internal.GetProgramsResponseHelper((GetProgramsResponse)(object)value);
                helper.ProgramsPlural = null;
                text = JsonSerializer.Serialize(helper, jsonSerializerOptions);
            }
            else
            {
                text = JsonSerializer.Serialize(value, jsonSerializerOptions);
            }

            if (protocolSettings.UrlEncodedRequests && typeof(TValue).IsSubclassOf(typeof(RequestBase)))
            {
                text = System.Net.WebUtility.UrlEncode(text);
            }

            if (protocolSettings.UrlEncodedResponses && typeof(TValue).IsSubclassOf(typeof(ResponseBase)))
            {
                text = System.Net.WebUtility.UrlEncode(text);
            }

            return(text);
        }
        private static void ValidateObject(GetProgramsResponseHelper value, bool expectNonEmptySingular, bool expectNonEmptyPlural)
        {
            value = value ?? throw new ArgumentNullException(nameof(value));

            Assert.Equal("error", value.Status);
            Assert.Equal(11, value.ErrorCode);
            Assert.Equal("Hello, World!", value.Message);

            if (expectNonEmptySingular)
            {
                Assert.NotNull(value.ProgramsSingular);
                Assert.Equal(2, value.ProgramsSingular.Count);
                Assert.Equal("code1s", value.ProgramsSingular[0].Code);
                Assert.Equal("name1s", value.ProgramsSingular[0].Name);
                Assert.Equal("code2s", value.ProgramsSingular[1].Code);
                Assert.Equal("name2s", value.ProgramsSingular[1].Name);
            }
            else
            {
                Assert.Null(value.ProgramsSingular);
            }

            if (expectNonEmptyPlural)
            {
                Assert.NotNull(value.ProgramsPlural);
                Assert.Equal(2, value.ProgramsPlural.Count);
                Assert.Equal("code1p", value.ProgramsPlural[0].Code);
                Assert.Equal("name1p", value.ProgramsPlural[0].Name);
                Assert.Equal("code2p", value.ProgramsPlural[1].Code);
                Assert.Equal("name2p", value.ProgramsPlural[1].Name);
            }
            else
            {
                Assert.Null(value.ProgramsPlural);
            }
        }