Skip to content

Commit 26d821a

Browse files
committed
[dotnet] Parse response before deserialization
1 parent 0b98c78 commit 26d821a

File tree

1 file changed

+26
-28
lines changed

1 file changed

+26
-28
lines changed

dotnet/src/webdriver/Response.cs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,21 @@
1919

2020
using OpenQA.Selenium.Internal;
2121
using System;
22-
using System.Collections.Generic;
2322
using System.Diagnostics.CodeAnalysis;
2423
using System.Globalization;
2524
using System.Text.Json;
25+
using System.Text.Json.Nodes;
2626
using System.Text.Json.Serialization;
2727

2828
#nullable enable
2929

3030
namespace OpenQA.Selenium
3131
{
3232
/// <summary>
33-
/// Handles reponses from the browser
33+
/// Handles responses from the browser
3434
/// </summary>
3535
public class Response
3636
{
37-
private static readonly JsonSerializerOptions s_jsonSerializerOptions = new()
38-
{
39-
TypeInfoResolver = ResponseJsonSerializerContext.Default,
40-
Converters = { new ResponseValueJsonConverter() } // we still need it to make `Object` as `Dictionary`
41-
};
42-
4337
/// <summary>
4438
/// Initializes a new instance of the <see cref="Response"/> class
4539
/// </summary>
@@ -82,18 +76,18 @@ public Response(string? sessionId, object? value, WebDriverResult status)
8276
/// <exception cref="JsonException">If <paramref name="value"/> is not a valid JSON object.</exception>
8377
public static Response FromJson(string value)
8478
{
85-
Dictionary<string, object?> rawResponse = JsonSerializer.Deserialize<Dictionary<string, object?>>(value, s_jsonSerializerOptions)
86-
?? throw new WebDriverException("JSON success response returned \"null\" value");
79+
JsonObject rawResponse = JsonNode.Parse(value) as JsonObject
80+
?? throw new WebDriverException($"JSON success response did not return a dictionary{Environment.NewLine}{value}");
8781

88-
object? contents;
82+
JsonNode? contents;
8983
string? sessionId = null;
9084

91-
if (rawResponse.TryGetValue("sessionId", out object? s) && s is not null)
85+
if (rawResponse.TryGetPropertyValue("sessionId", out JsonNode? s) && s is not null)
9286
{
9387
sessionId = s.ToString();
9488
}
9589

96-
if (rawResponse.TryGetValue("value", out object? valueObj))
90+
if (rawResponse.TryGetPropertyValue("value", out JsonNode? valueObj))
9791
{
9892
contents = valueObj;
9993
}
@@ -107,7 +101,7 @@ public static Response FromJson(string value)
107101

108102
// Special-case for the new session command, where the "capabilities"
109103
// property of the response is the actual value we're interested in.
110-
if (rawResponse.TryGetValue("capabilities", out object? capabilities))
104+
if (rawResponse.TryGetPropertyValue("capabilities", out JsonNode? capabilities))
111105
{
112106
contents = capabilities;
113107
}
@@ -117,14 +111,14 @@ public static Response FromJson(string value)
117111
}
118112
}
119113

120-
if (contents is Dictionary<string, object?> valueDictionary)
114+
if (contents is JsonObject valueDictionary)
121115
{
122116
// Special case code for the new session command. If the response contains
123117
// sessionId and capabilities properties, fix up the session ID and value members.
124-
if (valueDictionary.TryGetValue("sessionId", out object? session))
118+
if (valueDictionary.TryGetPropertyValue("sessionId", out JsonNode? session))
125119
{
126120
sessionId = session.ToString();
127-
if (valueDictionary.TryGetValue("capabilities", out object? capabilities))
121+
if (valueDictionary.TryGetPropertyValue("capabilities", out JsonNode? capabilities))
128122
{
129123
contents = capabilities;
130124
}
@@ -135,7 +129,9 @@ public static Response FromJson(string value)
135129
}
136130
}
137131

138-
return new Response(sessionId, contents, WebDriverResult.Success);
132+
var contentsDictionary = JsonSerializer.Deserialize(contents, ResponseJsonSerializerContext.Default.Object);
133+
134+
return new Response(sessionId, contentsDictionary, WebDriverResult.Success);
139135
}
140136

141137
/// <summary>
@@ -181,29 +177,30 @@ public WebDriverResult Status
181177
/// <exception cref="WebDriverException">If the JSON dictionary is not in the expected state, per spec.</exception>
182178
public static Response FromErrorJson(string value)
183179
{
184-
Dictionary<string, object?> deserializedResponse = JsonSerializer.Deserialize<Dictionary<string, object?>>(value, s_jsonSerializerOptions)
185-
?? throw new WebDriverException("JSON error response returned \"null\" value");
180+
JsonObject responseObject = JsonNode.Parse(value) as JsonObject
181+
?? throw new WebDriverException($"JSON error response did not return an object{Environment.NewLine}{value}");
186182

187-
if (!deserializedResponse.TryGetValue("value", out object? valueObject))
183+
if (!responseObject.TryGetPropertyValue("value", out JsonNode? valueNode))
188184
{
189-
throw new WebDriverException($"The 'value' property was not found in the response:{Environment.NewLine}{value}");
185+
throw new WebDriverException($"The 'value' property was not found in the response{Environment.NewLine}{value}");
190186
}
191187

192-
if (valueObject is not Dictionary<string, object?> valueDictionary)
188+
if (valueNode is not JsonObject valueObject)
193189
{
194-
throw new WebDriverException($"The 'value' property is not a dictionary of <string, object>{Environment.NewLine}{value}");
190+
throw new WebDriverException($"The 'value' property is not a dictionary{Environment.NewLine}{value}");
195191
}
196192

197-
if (!valueDictionary.TryGetValue("error", out object? errorObject))
193+
if (!valueObject.TryGetPropertyValue("error", out JsonNode? errorObject))
198194
{
199-
throw new WebDriverException($"The 'value > error' property was not found in the response:{Environment.NewLine}{value}");
195+
throw new WebDriverException($"The 'value > error' property was not found in the response{Environment.NewLine}{value}");
200196
}
201197

202-
if (errorObject is not string errorString)
198+
if (errorObject is not JsonValue errorValue || !errorValue.TryGetValue(out string? errorString))
203199
{
204200
throw new WebDriverException($"The 'value > error' property is not a string{Environment.NewLine}{value}");
205201
}
206202

203+
var valueDictionary = JsonSerializer.Deserialize(valueObject, ResponseJsonSerializerContext.Default.Object);
207204
WebDriverResult status = WebDriverError.ResultFromError(errorString);
208205

209206
return new Response(sessionId: null, valueDictionary, status);
@@ -243,6 +240,7 @@ public override string ToString()
243240
}
244241
}
245242

246-
[JsonSerializable(typeof(Dictionary<string, object>))]
243+
[JsonSerializable(typeof(object))]
244+
[JsonSourceGenerationOptions(Converters = [typeof(ResponseValueJsonConverter)])] // we still need it to make `Object` as `Dictionary`
247245
internal sealed partial class ResponseJsonSerializerContext : JsonSerializerContext;
248246
}

0 commit comments

Comments
 (0)