public override void WriteJson(JsonWriter?writer, object?value, JsonSerializer?serializer) { if (!(value is OpenTokBroadcastStartRequest obj)) { serializer !.Serialize(writer !, value !); return; } var outputs = new Dictionary <string, object>(); if (obj.Hls) { outputs.Add("hls", new object()); } outputs.Add("rtmp", obj.Rtmp); var dict = new Dictionary <string, object> { ["sessionId"] = obj.SessionId, ["layout"] = obj.Layout, ["maxDuration"] = (int)obj.Duration.TotalSeconds, ["outputs"] = outputs, ["resolution"] = obj.Resolution }; serializer !.Serialize(writer !, dict); }
/// <summary> /// Imports the Lua module with the specified name and evaluates the specified Lua code with it. /// </summary> /// <typeparam name="T">The expected evaluation return value type.</typeparam> /// <param name="site">The MediaWiki site on which to evaluate the module.</param> /// <param name="moduleName">Name of the module to be imported, with or without <c>Module:</c> prefix.</param> /// <param name="epilog">The Lua code snippet used to return value from the imported module (denoted as <c>p</c> in Lua), /// or <c>null</c> to use default epilog (<c>return p</c>).</param> /// <param name="serializer">The JsonSerializer used to deserialize the return value from JSON, or <c>null</c> to use default JSON serializer.</param> /// <param name="cancellationToken">A token used to cancel the operation.</param> /// <returns>The deserialized Lua evaluation result.</returns> public static Task <T> ScribuntoLoadDataAsync <T>(this WikiSite site, string moduleName, string?epilog, JsonSerializer?serializer, CancellationToken cancellationToken) { if (site == null) { throw new ArgumentNullException(nameof(site)); } if (string.IsNullOrEmpty(moduleName)) { throw new ArgumentException(Prompts.ExceptionArgumentNullOrEmpty, nameof(moduleName)); } cancellationToken.ThrowIfCancellationRequested(); var moduleLink = WikiLink.Parse(site, moduleName); var normalizedModuleName = moduleLink.FullTitle; if (string.IsNullOrEmpty(moduleLink.NamespaceName)) { normalizedModuleName = "Module:" + normalizedModuleName; } if (epilog == null) { epilog = "return p"; } var sb = new StringBuilder("-- ScribuntoLoadDataAsync\n\n", 64 + normalizedModuleName.Length + epilog.Length); sb.Append("local p = require([==["); sb.Append(normalizedModuleName); sb.Append("]==])\n\n"); sb.Append(epilog); sb.AppendLine(); return(ScribuntoExecuteLuaAsync <T>(site, sb.ToString(), serializer, cancellationToken)); }
/// <summary> /// Deserialize a JToken into an object /// </summary> /// <typeparam name="T">The type to deserialize into</typeparam> /// <param name="obj">The data to deserialize</param> /// <param name="serializer">A specific serializer to use</param> /// <param name="requestId">Id of the request the data is returned from (used for grouping logging by request)</param> /// <returns></returns> protected CallResult <T> Deserialize <T>(JToken obj, JsonSerializer?serializer = null, int?requestId = null) { serializer ??= defaultSerializer; try { return(new CallResult <T>(obj.ToObject <T>(serializer) !)); } catch (JsonReaderException jre) { var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonReaderException: {jre.Message} Path: {jre.Path}, LineNumber: {jre.LineNumber}, LinePosition: {jre.LinePosition}, data: {obj}"; log.Write(LogLevel.Error, info); return(new CallResult <T>(new DeserializeError(info, obj))); } catch (JsonSerializationException jse) { var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize JsonSerializationException: {jse.Message} data: {obj}"; log.Write(LogLevel.Error, info); return(new CallResult <T>(new DeserializeError(info, obj))); } catch (Exception ex) { var exceptionInfo = ex.ToLogString(); var info = $"{(requestId != null ? $"[{requestId}] " : "")}Deserialize Unknown Exception: {exceptionInfo}, data: {obj}"; log.Write(LogLevel.Error, info); return(new CallResult <T>(new DeserializeError(info, obj))); } }
/// <summary> /// Evaluates an ad-hoc Lua module with the specified module content in Scribunto Lua console, and gets the returned value. /// </summary> /// <typeparam name="T">The expected evaluation return value type.</typeparam> /// <param name="site">The MediaWiki site on which to evaluate the module.</param> /// <param name="moduleContent">The module content to be evaluated. You need to use <c>return</c> statement to return any value from the module.</param> /// <param name="serializer">The JsonSerializer used to deserialize the return value from JSON, or <c>null</c> to use default JSON serializer.</param> /// <param name="cancellationToken">A token used to cancel the operation.</param> /// <returns>The deserialized Lua evaluation result.</returns> /// <remarks> /// <para>This method will let MediaWiki server to evaluate <paramref name="moduleContent"/> as an ad-hoc Lua module, /// and to serialize the return value into JSON with /// <a href="https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#mw.text.jsonEncode"><c>mw.text.jsonEncode</c></a> /// method. The returned value will be deserialized by WCL with your specified <paramref name="serializer"/>. /// You need to read the documentation for <c>jsonEncode</c> carefully, as there might be some common pitfalls, such as /// empty Lua table will be serialized as JSON <c>[]</c> rather than <c>{}</c>.</para> /// <para>Due to the nature of JSON serialization and deserialization, /// you cannot return Lua functions or tables containing functions in the module.</para> /// </remarks> public static async Task <T> ScribuntoExecuteLuaAsync <T>(this WikiSite site, string moduleContent, JsonSerializer?serializer, CancellationToken cancellationToken) { if (site == null) { throw new ArgumentNullException(nameof(site)); } if (string.IsNullOrEmpty(moduleContent)) { throw new ArgumentException(Prompts.ExceptionArgumentNullOrEmpty, nameof(moduleContent)); } cancellationToken.ThrowIfCancellationRequested(); if (serializer == null) { serializer = defaultJsonSerializer; } var result = await ScribuntoConsole.InvokeApiAsync(site, null, ScribuntoConsole.AdhocModuleTitlePrefix, moduleContent, "=mw.text.jsonEncode(p)", true, cancellationToken); if (string.IsNullOrEmpty(result.ReturnValue)) { throw new UnexpectedDataException(Prompts.ExceptionScribuntoConsoleReturnEmpty); } using var sr = new StringReader(result.ReturnValue); using var jr = new JsonTextReader(sr); return(serializer.Deserialize <T>(jr)); }
protected virtual async Task <WebCallResult <T> > SendRequestAsync <T>( RestApiClient apiClient, Uri uri, HttpMethod method, CancellationToken cancellationToken, Dictionary <string, object>?parameters = null, bool signed = false, HttpMethodParameterPosition?parameterPosition = null, ArrayParametersSerialization?arraySerialization = null, int requestWeight = 1, JsonSerializer?deserializer = null, Dictionary <string, string>?additionalHeaders = null, bool ignoreRatelimit = false ) where T : class { var requestId = NextId(); if (signed) { var syncTimeResult = await apiClient.SyncTimeAsync().ConfigureAwait(false); if (!syncTimeResult) { log.Write(LogLevel.Debug, $"[{requestId}] Failed to sync time, aborting request: " + syncTimeResult.Error); return(syncTimeResult.As <T>(default));
/// <summary> /// Declares that an object returned by the API should be deserialized from JSON if the /// response falls within one of the specified status code ranges. /// </summary> /// <typeparam name="T">The request.</typeparam> /// <param name="builder">The builder.</param> /// <param name="jsonSerializer"> /// A <see cref="JsonSerializer"/> which should be used for the deserialization. /// </param> /// <param name="forStatusCodes"> /// A set of status codes for which the response type is the result. /// </param> /// <returns> /// A generic <see cref="ApiRequest"/> variation. /// </returns> /// <exception cref="ArgumentNullException"> /// * <paramref name="builder"/> /// * <paramref name="forStatusCodes"/> /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="forStatusCodes"/> is empty. /// </exception> public static T AsJson <T>( this ResponseTypeInfoBuilder <T> builder, JsonSerializer?jsonSerializer, params StatusCodeRange[] forStatusCodes) where T : ApiRequestBase { return(builder.AsJson(jsonSerializer, (IEnumerable <StatusCodeRange>)forStatusCodes)); }
protected virtual async Task <WebCallResult <T> > SendRequestAsync <T>( Uri uri, HttpMethod method, CancellationToken cancellationToken, Dictionary <string, object>?parameters = null, bool signed = false, bool checkResult = true, HttpMethodParameterPosition?parameterPosition = null, ArrayParametersSerialization?arraySerialization = null, int credits = 1, JsonSerializer?deserializer = null, Dictionary <string, string>?additionalHeaders = null) where T : class { var requestId = NextId(); log.Write(LogLevel.Debug, $"[{requestId}] Creating request for " + uri); if (signed && authProvider == null) { log.Write(LogLevel.Warning, $"[{requestId}] Request {uri.AbsolutePath} failed because no ApiCredentials were provided"); return(new WebCallResult <T>(null, null, null, new NoApiCredentialsError())); } var paramsPosition = parameterPosition ?? ParameterPositions[method]; var request = ConstructRequest(uri, method, parameters, signed, paramsPosition, arraySerialization ?? this.arraySerialization, requestId, additionalHeaders); foreach (var limiter in RateLimiters) { var limitResult = limiter.LimitRequest(this, uri.AbsolutePath, RateLimitBehaviour, credits); if (!limitResult.Success) { log.Write(LogLevel.Information, $"[{requestId}] Request {uri.AbsolutePath} failed because of rate limit"); return(new WebCallResult <T>(null, null, null, limitResult.Error)); } if (limitResult.Data > 0) { log.Write(LogLevel.Information, $"[{requestId}] Request {uri.AbsolutePath} was limited by {limitResult.Data}ms by {limiter.GetType().Name}"); } } string?paramString = ""; if (paramsPosition == HttpMethodParameterPosition.InBody) { paramString = " with request body " + request.Content; } if (log.Level == LogLevel.Trace) { var headers = request.GetHeaders(); if (headers.Any()) { paramString += " with headers " + string.Join(", ", headers.Select(h => h.Key + $"=[{string.Join(",", h.Value)}]")); } } log.Write(LogLevel.Debug, $"[{requestId}] Sending {method}{(signed ? " signed" : "")} request to {request.Uri}{paramString ?? " "}{(apiProxy == null ? "" : $" via proxy {apiProxy.Host}")}");
private static string SerializeJson(object value, JsonSerializer?serializer = null) { if (serializer == null) { return(JsonConvert.SerializeObject(value, JsonConfig.Default)); } using var writer = new StringWriter(); serializer.Serialize(writer, value); return(writer.ToString()); }
/// <summary> /// Declares that an object returned by the API should be deserialized from JSON if the /// response falls within one of the specified status code ranges. /// </summary> /// <typeparam name="T">The request.</typeparam> /// <param name="builder">The builder.</param> /// <param name="jsonSerializer"> /// A <see cref="JsonSerializer"/> which should be used for the deserialization. /// </param> /// <param name="forStatusCodes"> /// A set of status codes for which the response type is the result. /// </param> /// <returns> /// A generic <see cref="ApiRequest"/> variation. /// </returns> /// <exception cref="ArgumentNullException"> /// * <paramref name="builder"/> /// * <paramref name="forStatusCodes"/> /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="forStatusCodes"/> is empty. /// </exception> public static T AsJson <T>( this ResponseTypeInfoBuilder <T> builder, JsonSerializer?jsonSerializer, IEnumerable <StatusCodeRange> forStatusCodes) where T : ApiRequestBase { return(AsJson(builder, Factory, forStatusCodes)); JsonHttpContentSerializer Factory() => new JsonHttpContentSerializer(jsonSerializer); }
/// <inheritdoc /> public override void WriteJson(JsonWriter writer, object value, JsonSerializer?serializer) { var signature = (UnblindedSignature)value; var c = new BigInteger(signature.C.ToBytes(), isUnsigned: true, isBigEndian: true); var s = new BigInteger(signature.S.ToBytes(), isUnsigned: true, isBigEndian: true); writer.WriteStartArray(); writer.WriteValue(c.ToString()); writer.WriteValue(s.ToString()); writer.WriteEndArray(); }
public static Task <T?> TryReadJsonAs <T>([NotNull] this HttpResponseMessage response, bool allowAnyResponseCode = false, ILogger?logger = null, JsonSerializer?serializer = null) where T : class { if (response == null) { throw new ArgumentNullException(nameof(response)); } return(InternalTryReadJsonAs <T>(response, allowAnyResponseCode, logger, serializer)); }
/// <summary> /// Deserialize a string into an object /// </summary> /// <typeparam name="T">The type to deserialize into</typeparam> /// <param name="data">The data to deserialize</param> /// <param name="serializer">A specific serializer to use</param> /// <param name="requestId">Id of the request the data is returned from (used for grouping logging by request)</param> /// <returns></returns> protected CallResult <T> Deserialize <T>(string data, JsonSerializer?serializer = null, int?requestId = null) { var tokenResult = ValidateJson(data); if (!tokenResult) { log.Write(LogLevel.Error, tokenResult.Error !.Message); return(new CallResult <T>(tokenResult.Error)); } return(Deserialize <T>(tokenResult.Data, serializer, requestId)); }
private static async Task <T?> InternalTryReadJsonAs <T>([NotNull] this HttpResponseMessage response, bool allowAnyResponseCode = false, ILogger?logger = null, JsonSerializer?serializer = null) where T : class { logger ??= Logger.None !; if (!allowAnyResponseCode && !response.IsSuccessStatusCode) { logger.Error("Unexpected http response code {HttpResponseCode}", (int)response.StatusCode); return(default);
public static void MatchNamedSnapshot( this ObjectAssertions assertions, string snapshotFileName, JsonSerializer?serializer = null, [CallerFilePath] string?filePath = null) { MatchSnapshotInternal <object>( assertions, assertions.Subject.GetType(), serializer, x => x, filePath, snapshotFileName); }
public static AndWhichConstraint <ObjectAssertions, T> MatchNamedSnapshot <T>( this ObjectAssertions assertions, string snapshotFileName, JsonSerializer?serializer = null, Func <EquivalencyAssertionOptions <object>, EquivalencyAssertionOptions <object> >? equivalencyConfig = null, [CallerFilePath] string?filePath = null) { // ReSharper disable once ExplicitCallerInfoArgument return(MatchSnapshotInternal( assertions, typeof(T), serializer, equivalencyConfig, filePath, snapshotFileName) .And.BeAssignableTo <T>()); }
private static AndConstraint <ObjectAssertions> MatchSnapshotInternal <T>( ObjectAssertions assertions, Type deserializationType, JsonSerializer?serializer, Func <EquivalencyAssertionOptions <T>, EquivalencyAssertionOptions <T> >? equivalencyConfig, string?filePath, string?snapshotFileName) { var sourceFilePathNotNull = SourceFilePathWithoutExtension(filePath); var fileNameNotNull = snapshotFileName ?? throw new ArgumentNullException(nameof(snapshotFileName)); var matcher = new SnapshotMatcher( new Snapshotter( sourceFilePathNotNull, fileNameNotNull)); return(matcher.Match(assertions, deserializationType, serializer, equivalencyConfig)); }
protected virtual async Task <WebCallResult <T> > SendRequest <T>(Uri uri, HttpMethod method, CancellationToken cancellationToken, Dictionary <string, object>?parameters = null, bool signed = false, bool checkResult = true, PostParameters?postPosition = null, ArrayParametersSerialization?arraySerialization = null, int credits = 1, JsonSerializer?deserializer = null) where T : class { var requestId = NextId(); log.Write(LogVerbosity.Debug, $"[{requestId}] Creating request for " + uri); if (signed && authProvider == null) { log.Write(LogVerbosity.Warning, $"[{requestId}] Request {uri.AbsolutePath} failed because no ApiCredentials were provided"); return(new WebCallResult <T>(null, null, null, new NoApiCredentialsError())); } var request = ConstructRequest(uri, method, parameters, signed, postPosition ?? postParametersPosition, arraySerialization ?? this.arraySerialization, requestId); foreach (var limiter in RateLimiters) { var limitResult = limiter.LimitRequest(this, uri.AbsolutePath, RateLimitBehaviour, credits); if (!limitResult.Success) { log.Write(LogVerbosity.Debug, $"[{requestId}] Request {uri.AbsolutePath} failed because of rate limit"); return(new WebCallResult <T>(null, null, null, limitResult.Error)); } if (limitResult.Data > 0) { log.Write(LogVerbosity.Debug, $"[{requestId}] Request {uri.AbsolutePath} was limited by {limitResult.Data}ms by {limiter.GetType().Name}"); } } string?paramString = null; if (method == HttpMethod.Post) { paramString = " with request body " + request.Content; } log.Write(LogVerbosity.Debug, $"[{requestId}] Sending {method}{(signed ? " signed" : "")} request to {request.Uri}{paramString ?? " "}{(apiProxy == null ? "" : $" via proxy {apiProxy.Host}")}");
public override void WriteJson(JsonWriter?writer, object?value, JsonSerializer?serializer) { if (!(value is OpenTokArchiveStartRequest obj)) { serializer !.Serialize(writer !, value); return; } var dict = new Dictionary <string, object?> { ["sessionId"] = obj.SessionId, ["hasAudio"] = obj.HasAudio, ["hasVideo"] = obj.HasVideo, ["name"] = obj.Name, ["outputMode"] = obj.OutputMode }; if (obj.OutputMode == "composed") { dict.Add("layout", obj.Layout); dict.Add("resolution", obj.Resolution); } serializer !.Serialize(writer !, dict); }
public AndConstraint <ObjectAssertions> Match <T>( ObjectAssertions assertions, Type deserializationType, JsonSerializer?serializer, Func <EquivalencyAssertionOptions <T>, EquivalencyAssertionOptions <T> >?config) { serializer ??= new JsonSerializer(); var subject = assertions.Subject; var snapshot = _snapshotter.GetOrCreateSnapshot(subject, serializer); var actualJson = ToJTokenUsingSerializer(assertions, serializer); actualJson.Should() .BeEquivalentTo(snapshot, $"snapshot {_snapshotter.SnapshotPath} doesn't match"); var deserializedSnapshot = snapshot?.ToObject(deserializationType, serializer); deserializedSnapshot.Should() .BeOfType(subject.GetType()) .And.BeEquivalentTo((T)subject, config ?? (x => x)); return(deserializedSnapshot.Should().BeAssignableTo(deserializationType)); }
public WordPressEntitySet(HttpContent httpContent, bool isError = false, bool throwExceptions = true) : this(throwExceptions) { _jsonSerializer = JsonSerializer.Create(_jsonSerializerSettings); using (var stream = httpContent.ReadAsStreamAsync().GetAwaiter().GetResult()) { using (var reader = new StreamReader(stream)) { using (var json = new JsonTextReader(reader)) { if (!isError) { this.Value = _jsonSerializer.Deserialize <List <TWordPressEntity> >(json); this.Raw = ToRaw(this.Value); } else { this.Error = _jsonSerializer.Deserialize <ApiError>(json); this.RawError = ToRawError(this.Error); } } } } }
protected virtual async Task <WebCallResult> SendRequestAsync(RestApiClient apiClient, Uri uri, HttpMethod method, CancellationToken cancellationToken, Dictionary <string, object>?parameters = null, bool signed = false, HttpMethodParameterPosition?parameterPosition = null, ArrayParametersSerialization?arraySerialization = null, int requestWeight = 1, JsonSerializer?deserializer = null, Dictionary <string, string>?additionalHeaders = null, bool ignoreRatelimit = false) { var request = await PrepareRequestAsync(apiClient, uri, method, cancellationToken, parameters, signed, parameterPosition, arraySerialization, requestWeight, deserializer, additionalHeaders, ignoreRatelimit).ConfigureAwait(false); if (!request) { return(new WebCallResult(request.Error !)); } var result = await GetResponseAsync <object>(apiClient, request.Data, deserializer, cancellationToken, true).ConfigureAwait(false); return(result.AsDataless()); }
/// <inheritdoc /> public override object ReadJson(JsonReader reader, Type?objectType, object?existingValue, JsonSerializer?serializer) { JArray arr = JArray.Load(reader); var carr = ToFixedLengthByteArray(StringToBigInteger(arr[0].Value <string>())); var sarr = ToFixedLengthByteArray(StringToBigInteger(arr[1].Value <string>())); var signatureBytes = carr.Concat(sarr).ToArray(); var signature = ByteHelpers.ToHex(signatureBytes); var sig = UnblindedSignature.Parse(signature); return(sig); }
/// <summary> /// Imports the Lua module with the specified name and gets the module content. /// </summary> /// <returns>The deserialized Lua evaluation result of the module.</returns> /// <remarks> /// This overload is intended to provide similar behavior to /// <a href="https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#mw.loadData"><c>mw.loadData</c></a>, /// it works as long as the imported module meets the requirement of <c>loadData</c> function. /// </remarks> /// <inheritdoc cref="ScribuntoLoadDataAsync{T}(WikiSite,string,string,JsonSerializer,CancellationToken)"/> public static Task <T> ScribuntoLoadDataAsync <T>(this WikiSite site, string moduleName, JsonSerializer?serializer, CancellationToken cancellationToken) { return(ScribuntoLoadDataAsync <T>(site, moduleName, null, serializer, cancellationToken)); }
/// <summary> /// Deserialize a string into an object /// </summary> /// <typeparam name="T">The type to deserialize into</typeparam> /// <param name="data">The data to deserialize</param> /// <param name="checkObject">Whether or not the parsing should be checked for missing properties (will output data to the logging if log verbosity is Debug)</param> /// <param name="serializer">A specific serializer to use</param> /// <returns></returns> protected CallResult <T> Deserialize <T>(string data, bool checkObject = true, JsonSerializer?serializer = null) { var tokenResult = ValidateJson(data); return(!tokenResult ? new CallResult <T>(default, tokenResult.Error) : Deserialize <T>(tokenResult.Data, checkObject, serializer));
private void HandleSingleToArrayData <T>(string name, JArray dataArray, Action <IEnumerable <T> > handler, JsonSerializer?serializer = null) { var wrapperArray = new JArray(); wrapperArray.Add(dataArray); var desResult = Deserialize <IEnumerable <T> >(wrapperArray, serializer: serializer); if (!desResult) { log.Write(LogVerbosity.Warning, $"Failed to deserialize {name} object: " + desResult.Error); return; } handler(desResult.Data); }
public JsonNetContent(object value, JsonSerializer?serializer = null) : base(SerializeJson(value, serializer), Encoding.UTF8, "application/json") { }
/// <summary> /// Создает экземпляр класса <see cref="DefaultJsonSerializer"/>. /// </summary> /// <param name="json">Сериализатор Newtonsoft.Json.</param> public DefaultJsonSerializer(JsonSerializer?json = null) { _json = json ?? new JsonSerializer(); ContentType = "application/json"; }
/// <summary> /// Initializes a new instance of the <see cref="JsonHttpContentSerializer"/> class with /// an optional <see cref="Newtonsoft.Json.JsonSerializer"/> to be used /// for the (de-)serialization. /// </summary> /// <param name="jsonSerializer"> /// The <see cref="Newtonsoft.Json.JsonSerializer"/> to be used for /// (de-)serializing the resource objects. /// /// If <see langword="null"/>, a default <see cref="Newtonsoft.Json.JsonSerializer"/> /// instance is used for (de-)serialization. /// </param> public JsonHttpContentSerializer(JsonSerializer?jsonSerializer) { JsonSerializer = jsonSerializer ?? DefaultJsonSerializer; }
/// <summary> /// Deserialize a string into an object /// </summary> /// <typeparam name="T">The type to deserialize into</typeparam> /// <param name="data">The data to deserialize</param> /// <param name="checkObject">Whether or not the parsing should be checked for missing properties (will output data to the logging if log verbosity is Debug)</param> /// <param name="serializer">A specific serializer to use</param> /// <returns></returns> protected CallResult <T> Deserialize <T>(string data, bool checkObject = true, JsonSerializer?serializer = null) { var tokenResult = ValidateJson(data); if (!tokenResult) { log.Write(LogVerbosity.Error, tokenResult.Error !.Message); return(new CallResult <T>(default, tokenResult.Error));
/// <summary> /// Deserialize a string into an object /// </summary> /// <typeparam name="T">The type to deserialize into</typeparam> /// <param name="data">The data to deserialize</param> /// <param name="checkObject">Whether or not the parsing should be checked for missing properties (will output data to the logging if log verbosity is Debug)</param> /// <param name="serializer">A specific serializer to use</param> /// <param name="requestId">Id of the request the data is returned from (used for grouping logging by request)</param> /// <returns></returns> protected CallResult <T> Deserialize <T>(string data, bool?checkObject = null, JsonSerializer?serializer = null, int?requestId = null) { var tokenResult = ValidateJson(data); if (!tokenResult) { log.Write(LogLevel.Error, tokenResult.Error !.Message); return(new CallResult <T>(default, tokenResult.Error));