diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/EvaluateResultConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/EvaluateResultConverter.cs index c6ae850e5a118..6a03de48ebd3f 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/EvaluateResultConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/EvaluateResultConverter.cs @@ -17,6 +17,7 @@ // under the License. // +using OpenQA.Selenium.BiDi.Communication.Json.Internal; using OpenQA.Selenium.BiDi.Modules.Script; using System; using System.Text.Json; @@ -29,12 +30,10 @@ internal class EvaluateResultConverter : JsonConverter { public override EvaluateResult? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var jsonDocument = JsonDocument.ParseValue(ref reader); - - return jsonDocument.RootElement.GetProperty("type").ToString() switch + return reader.GetDiscriminator("type") switch { - "success" => jsonDocument.Deserialize(options), - "exception" => jsonDocument.Deserialize(options), + "success" => JsonSerializer.Deserialize(ref reader, options), + "exception" => JsonSerializer.Deserialize(ref reader, options), _ => null, }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/LogEntryConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/LogEntryConverter.cs index 82cf56dd6013b..07bbbcd4221e3 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/LogEntryConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/LogEntryConverter.cs @@ -17,6 +17,7 @@ // under the License. // +using OpenQA.Selenium.BiDi.Communication.Json.Internal; using OpenQA.Selenium.BiDi.Modules.Log; using System; using System.Text.Json; @@ -29,12 +30,10 @@ internal class LogEntryConverter : JsonConverter { public override Modules.Log.LogEntry? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var jsonDocument = JsonDocument.ParseValue(ref reader); - - return jsonDocument.RootElement.GetProperty("type").ToString() switch + return reader.GetDiscriminator("type") switch { - "console" => jsonDocument.Deserialize(options), - "javascript" => jsonDocument.Deserialize(options), + "console" => JsonSerializer.Deserialize(ref reader, options), + "javascript" => JsonSerializer.Deserialize(ref reader, options), _ => null, }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/MessageConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/MessageConverter.cs index 8e10f9b0565d9..3c9155f8bf979 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/MessageConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/MessageConverter.cs @@ -17,6 +17,7 @@ // under the License. // +using OpenQA.Selenium.BiDi.Communication.Json.Internal; using System; using System.Text.Json; using System.Text.Json.Serialization; @@ -28,13 +29,11 @@ internal class MessageConverter : JsonConverter { public override Message? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var jsonDocument = JsonDocument.ParseValue(ref reader); - - return jsonDocument.RootElement.GetProperty("type").ToString() switch + return reader.GetDiscriminator("type") switch { - "success" => jsonDocument.Deserialize(options), - "error" => jsonDocument.Deserialize(options), - "event" => jsonDocument.Deserialize(options), + "success" => JsonSerializer.Deserialize(ref reader, options), + "error" => JsonSerializer.Deserialize(ref reader, options), + "event" => JsonSerializer.Deserialize(ref reader, options), _ => null, }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RealmInfoConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RealmInfoConverter.cs index 650c3c8919cad..443d42331d1bc 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RealmInfoConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RealmInfoConverter.cs @@ -17,6 +17,7 @@ // under the License. // +using OpenQA.Selenium.BiDi.Communication.Json.Internal; using OpenQA.Selenium.BiDi.Modules.Script; using System; using System.Text.Json; @@ -29,18 +30,16 @@ internal class RealmInfoConverter : JsonConverter { public override RealmInfo? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var jsonDocument = JsonDocument.ParseValue(ref reader); - - return jsonDocument.RootElement.GetProperty("type").ToString() switch + return reader.GetDiscriminator("type") switch { - "window" => jsonDocument.Deserialize(options), - "dedicated-worker" => jsonDocument.Deserialize(options), - "shared-worker" => jsonDocument.Deserialize(options), - "service-worker" => jsonDocument.Deserialize(options), - "worker" => jsonDocument.Deserialize(options), - "paint-worklet" => jsonDocument.Deserialize(options), - "audio-worklet" => jsonDocument.Deserialize(options), - "worklet" => jsonDocument.Deserialize(options), + "window" => JsonSerializer.Deserialize(ref reader, options), + "dedicated-worker" => JsonSerializer.Deserialize(ref reader, options), + "shared-worker" => JsonSerializer.Deserialize(ref reader, options), + "service-worker" => JsonSerializer.Deserialize(ref reader, options), + "worker" => JsonSerializer.Deserialize(ref reader, options), + "paint-worklet" => JsonSerializer.Deserialize(ref reader, options), + "audio-worklet" => JsonSerializer.Deserialize(ref reader, options), + "worklet" => JsonSerializer.Deserialize(ref reader, options), _ => null, }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RemoteValueConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RemoteValueConverter.cs index f5319db4c5294..87adb82269d52 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RemoteValueConverter.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/Polymorphic/RemoteValueConverter.cs @@ -17,6 +17,7 @@ // under the License. // +using OpenQA.Selenium.BiDi.Communication.Json.Internal; using OpenQA.Selenium.BiDi.Modules.Script; using System; using System.Text.Json; @@ -29,41 +30,39 @@ internal class RemoteValueConverter : JsonConverter { public override RemoteValue? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var jsonDocument = JsonDocument.ParseValue(ref reader); - - if (jsonDocument.RootElement.ValueKind == JsonValueKind.String) + if (reader.TokenType == JsonTokenType.String) { - return new StringRemoteValue(jsonDocument.RootElement.GetString()!); + return new StringRemoteValue(reader.GetString()!); } - return jsonDocument.RootElement.GetProperty("type").ToString() switch + return reader.GetDiscriminator("type") switch { - "number" => jsonDocument.Deserialize(options), - "boolean" => jsonDocument.Deserialize(options), - "bigint" => jsonDocument.Deserialize(options), - "string" => jsonDocument.Deserialize(options), - "null" => jsonDocument.Deserialize(options), - "undefined" => jsonDocument.Deserialize(options), - "symbol" => jsonDocument.Deserialize(options), - "array" => jsonDocument.Deserialize(options), - "object" => jsonDocument.Deserialize(options), - "function" => jsonDocument.Deserialize(options), - "regexp" => jsonDocument.Deserialize(options), - "date" => jsonDocument.Deserialize(options), - "map" => jsonDocument.Deserialize(options), - "set" => jsonDocument.Deserialize(options), - "weakmap" => jsonDocument.Deserialize(options), - "weakset" => jsonDocument.Deserialize(options), - "generator" => jsonDocument.Deserialize(options), - "error" => jsonDocument.Deserialize(options), - "proxy" => jsonDocument.Deserialize(options), - "promise" => jsonDocument.Deserialize(options), - "typedarray" => jsonDocument.Deserialize(options), - "arraybuffer" => jsonDocument.Deserialize(options), - "nodelist" => jsonDocument.Deserialize(options), - "htmlcollection" => jsonDocument.Deserialize(options), - "node" => jsonDocument.Deserialize(options), - "window" => jsonDocument.Deserialize(options), + "number" => JsonSerializer.Deserialize(ref reader, options), + "boolean" => JsonSerializer.Deserialize(ref reader, options), + "bigint" => JsonSerializer.Deserialize(ref reader, options), + "string" => JsonSerializer.Deserialize(ref reader, options), + "null" => JsonSerializer.Deserialize(ref reader, options), + "undefined" => JsonSerializer.Deserialize(ref reader, options), + "symbol" => JsonSerializer.Deserialize(ref reader, options), + "array" => JsonSerializer.Deserialize(ref reader, options), + "object" => JsonSerializer.Deserialize(ref reader, options), + "function" => JsonSerializer.Deserialize(ref reader, options), + "regexp" => JsonSerializer.Deserialize(ref reader, options), + "date" => JsonSerializer.Deserialize(ref reader, options), + "map" => JsonSerializer.Deserialize(ref reader, options), + "set" => JsonSerializer.Deserialize(ref reader, options), + "weakmap" => JsonSerializer.Deserialize(ref reader, options), + "weakset" => JsonSerializer.Deserialize(ref reader, options), + "generator" => JsonSerializer.Deserialize(ref reader, options), + "error" => JsonSerializer.Deserialize(ref reader, options), + "proxy" => JsonSerializer.Deserialize(ref reader, options), + "promise" => JsonSerializer.Deserialize(ref reader, options), + "typedarray" => JsonSerializer.Deserialize(ref reader, options), + "arraybuffer" => JsonSerializer.Deserialize(ref reader, options), + "nodelist" => JsonSerializer.Deserialize(ref reader, options), + "htmlcollection" => JsonSerializer.Deserialize(ref reader, options), + "node" => JsonSerializer.Deserialize(ref reader, options), + "window" => JsonSerializer.Deserialize(ref reader, options), _ => null, }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Internal/JsonExtensions.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Internal/JsonExtensions.cs new file mode 100644 index 0000000000000..3a8b687665ac1 --- /dev/null +++ b/dotnet/src/webdriver/BiDi/Communication/Json/Internal/JsonExtensions.cs @@ -0,0 +1,53 @@ +// +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +using System.Text.Json; + +namespace OpenQA.Selenium.BiDi.Communication.Json.Internal; + +internal static class JsonExtensions +{ + public static string GetDiscriminator(this ref Utf8JsonReader reader, string name) + { + Utf8JsonReader readerClone = reader; + + if (readerClone.TokenType != JsonTokenType.StartObject) + throw new JsonException($"Cannot determine the discriminator of {readerClone.TokenType} token type while supported is {JsonTokenType.StartObject} only."); + + string? discriminator = null; + + readerClone.Read(); + while (readerClone.TokenType == JsonTokenType.PropertyName) + { + string? propertyName = readerClone.GetString(); + readerClone.Read(); + + if (propertyName == name) + { + discriminator = readerClone.GetString(); + break; + } + + readerClone.Skip(); + readerClone.Read(); + } + + return discriminator ?? throw new JsonException($"Couldn't determine '{name}' descriminator."); + } +}