Skip to content

Commit ab5b335

Browse files
RenderMichaelsandeepsuryaprasad
authored andcommitted
[dotnet] Parse response before deserialization (SeleniumHQ#15268)
* [dotnet] Parse response before deserialization * Handle if `value.sessionId` is `null` * null check instead
1 parent e281c70 commit ab5b335

File tree

1 file changed

+27
-29
lines changed

1 file changed

+27
-29
lines changed

dotnet/src/webdriver/Response.cs

Lines changed: 27 additions & 29 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>
@@ -62,18 +56,18 @@ public Response(string? sessionId, object? value, WebDriverResult status)
6256
/// <exception cref="JsonException">If <paramref name="value"/> is not a valid JSON object.</exception>
6357
public static Response FromJson(string value)
6458
{
65-
Dictionary<string, object?> rawResponse = JsonSerializer.Deserialize<Dictionary<string, object?>>(value, s_jsonSerializerOptions)
66-
?? throw new WebDriverException("JSON success response returned \"null\" value");
59+
JsonObject rawResponse = JsonNode.Parse(value) as JsonObject
60+
?? throw new WebDriverException($"JSON success response did not return a dictionary{Environment.NewLine}{value}");
6761

68-
object? contents;
62+
JsonNode? contents;
6963
string? sessionId = null;
7064

71-
if (rawResponse.TryGetValue("sessionId", out object? s) && s is not null)
65+
if (rawResponse.TryGetPropertyValue("sessionId", out JsonNode? s) && s is not null)
7266
{
7367
sessionId = s.ToString();
7468
}
7569

76-
if (rawResponse.TryGetValue("value", out object? valueObj))
70+
if (rawResponse.TryGetPropertyValue("value", out JsonNode? valueObj))
7771
{
7872
contents = valueObj;
7973
}
@@ -87,7 +81,7 @@ public static Response FromJson(string value)
8781

8882
// Special-case for the new session command, where the "capabilities"
8983
// property of the response is the actual value we're interested in.
90-
if (rawResponse.TryGetValue("capabilities", out object? capabilities))
84+
if (rawResponse.TryGetPropertyValue("capabilities", out JsonNode? capabilities))
9185
{
9286
contents = capabilities;
9387
}
@@ -97,14 +91,14 @@ public static Response FromJson(string value)
9791
}
9892
}
9993

100-
if (contents is Dictionary<string, object?> valueDictionary)
94+
if (contents is JsonObject valueDictionary)
10195
{
10296
// Special case code for the new session command. If the response contains
10397
// sessionId and capabilities properties, fix up the session ID and value members.
104-
if (valueDictionary.TryGetValue("sessionId", out object? session))
98+
if (valueDictionary.TryGetPropertyValue("sessionId", out JsonNode? session))
10599
{
106-
sessionId = session.ToString();
107-
if (valueDictionary.TryGetValue("capabilities", out object? capabilities))
100+
sessionId = session?.ToString();
101+
if (valueDictionary.TryGetPropertyValue("capabilities", out JsonNode? capabilities))
108102
{
109103
contents = capabilities;
110104
}
@@ -115,7 +109,9 @@ public static Response FromJson(string value)
115109
}
116110
}
117111

118-
return new Response(sessionId, contents, WebDriverResult.Success);
112+
var contentsDictionary = JsonSerializer.Deserialize(contents, ResponseJsonSerializerContext.Default.Object);
113+
114+
return new Response(sessionId, contentsDictionary, WebDriverResult.Success);
119115
}
120116

121117
/// <summary>
@@ -143,29 +139,30 @@ public static Response FromJson(string value)
143139
/// <exception cref="WebDriverException">If the JSON dictionary is not in the expected state, per spec.</exception>
144140
public static Response FromErrorJson(string value)
145141
{
146-
Dictionary<string, object?> deserializedResponse = JsonSerializer.Deserialize<Dictionary<string, object?>>(value, s_jsonSerializerOptions)
147-
?? throw new WebDriverException("JSON error response returned \"null\" value");
142+
JsonObject responseObject = JsonNode.Parse(value) as JsonObject
143+
?? throw new WebDriverException($"JSON error response did not return an object{Environment.NewLine}{value}");
148144

149-
if (!deserializedResponse.TryGetValue("value", out object? valueObject))
145+
if (!responseObject.TryGetPropertyValue("value", out JsonNode? valueNode))
150146
{
151-
throw new WebDriverException($"The 'value' property was not found in the response:{Environment.NewLine}{value}");
147+
throw new WebDriverException($"The 'value' property was not found in the response{Environment.NewLine}{value}");
152148
}
153149

154-
if (valueObject is not Dictionary<string, object?> valueDictionary)
150+
if (valueNode is not JsonObject valueObject)
155151
{
156-
throw new WebDriverException($"The 'value' property is not a dictionary of <string, object>{Environment.NewLine}{value}");
152+
throw new WebDriverException($"The 'value' property is not a dictionary{Environment.NewLine}{value}");
157153
}
158154

159-
if (!valueDictionary.TryGetValue("error", out object? errorObject))
155+
if (!valueObject.TryGetPropertyValue("error", out JsonNode? errorObject))
160156
{
161-
throw new WebDriverException($"The 'value > error' property was not found in the response:{Environment.NewLine}{value}");
157+
throw new WebDriverException($"The 'value > error' property was not found in the response{Environment.NewLine}{value}");
162158
}
163159

164-
if (errorObject is not string errorString)
160+
if (errorObject is not JsonValue errorValue || !errorValue.TryGetValue(out string? errorString))
165161
{
166162
throw new WebDriverException($"The 'value > error' property is not a string{Environment.NewLine}{value}");
167163
}
168164

165+
var valueDictionary = JsonSerializer.Deserialize(valueObject, ResponseJsonSerializerContext.Default.Object);
169166
WebDriverResult status = WebDriverError.ResultFromError(errorString);
170167

171168
return new Response(sessionId: null, valueDictionary, status);
@@ -205,6 +202,7 @@ public override string ToString()
205202
}
206203
}
207204

208-
[JsonSerializable(typeof(Dictionary<string, object>))]
205+
[JsonSerializable(typeof(object))]
206+
[JsonSourceGenerationOptions(Converters = [typeof(ResponseValueJsonConverter)])] // we still need it to make `Object` as `Dictionary`
209207
internal sealed partial class ResponseJsonSerializerContext : JsonSerializerContext;
210208
}

0 commit comments

Comments
 (0)