From 2f673ffd1fc2d7363f91ce96672ededffa029c19 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Tue, 11 Nov 2025 21:51:28 +0100 Subject: [PATCH] Add DeserializeTo --- .../ResponseBodyDeserializationTests.cs | 24 +++++++++ .../Response/Deserialization/Deserializer.cs | 52 ++++++++++++------- .../Response/VerifiableResponse.cs | 14 ++++- 3 files changed, 70 insertions(+), 20 deletions(-) diff --git a/RestAssured.Net.Tests/ResponseBodyDeserializationTests.cs b/RestAssured.Net.Tests/ResponseBodyDeserializationTests.cs index aa58277..1ddb8e7 100644 --- a/RestAssured.Net.Tests/ResponseBodyDeserializationTests.cs +++ b/RestAssured.Net.Tests/ResponseBodyDeserializationTests.cs @@ -99,6 +99,30 @@ public void ObjectCanBeDeserializedFromJson() Assert.That(firstPlace.IsCapital, Is.EqualTo(this.isCapital)); } + /// + /// A test demonstrating RestAssuredNet syntax for deserializing + /// a JSON response into an object when performing an HTTP GET. + /// + [Test] + public void ObjectCanBeDeserializedAsTypeFromJson() + { + this.CreateStubForJsonResponseBody(); + + Location responseLocation = Given() + .When() + .Get($"{MOCK_SERVER_BASE_URL}/json-deserialization") + .DeserializeTo(); + + Assert.That(responseLocation.Country, Is.EqualTo(this.country)); + Assert.That(responseLocation.Places?.Count, Is.EqualTo(2)); + + Place firstPlace = responseLocation.Places!.First(); + + Assert.That(firstPlace.Name, Is.EqualTo(this.placeName)); + Assert.That(firstPlace.Inhabitants, Is.EqualTo(this.placeInhabitants)); + Assert.That(firstPlace.IsCapital, Is.EqualTo(this.isCapital)); + } + /// /// A test demonstrating RestAssuredNet syntax for deserializing /// a JSON response into an object when performing an HTTP GET diff --git a/RestAssured.Net/Response/Deserialization/Deserializer.cs b/RestAssured.Net/Response/Deserialization/Deserializer.cs index 1d6f3ec..24429ad 100644 --- a/RestAssured.Net/Response/Deserialization/Deserializer.cs +++ b/RestAssured.Net/Response/Deserialization/Deserializer.cs @@ -13,11 +13,13 @@ // See the License for the specific language governing permissions and // limitations under the License. // + namespace RestAssured.Response.Deserialization { using System; using System.IO; using System.Net.Http; + using System.Threading.Tasks; using System.Xml.Serialization; using Newtonsoft.Json; using RestAssured.Response.Exceptions; @@ -36,9 +38,9 @@ internal class Deserializer /// The to use when deserializing to JSON. /// The deserialized response body object. /// Thrown when deserialization of the response body fails. - internal static object DeserializeResponseInto(HttpResponseMessage response, Type type, DeserializeAs deserializeAs, JsonSerializerSettings jsonSerializerSettings) + internal static object? DeserializeResponseInto(HttpResponseMessage response, Type type, DeserializeAs deserializeAs, JsonSerializerSettings jsonSerializerSettings) { - string responseBodyAsString = response.Content.ReadAsStringAsync().Result; + string responseBodyAsString = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); if (string.IsNullOrEmpty(responseBodyAsString)) { @@ -51,39 +53,51 @@ internal static object DeserializeResponseInto(HttpResponseMessage response, Typ { case DeserializeAs.UseResponseContentTypeHeaderValue: { - responseMediaType = response.Content.Headers.ContentType?.MediaType; - break; + responseMediaType = response.Content.Headers.ContentType?.MediaType; + break; } case DeserializeAs.Json: { - responseMediaType = "application/json"; - break; + responseMediaType = "application/json"; + break; } case DeserializeAs.Xml: { - responseMediaType = "application/xml"; - break; + responseMediaType = "application/xml"; + break; } } if (responseMediaType == null || responseMediaType.Contains("json")) { - return JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result, type, jsonSerializerSettings) ?? string.Empty; + return JsonConvert.DeserializeObject(responseBodyAsString, type, jsonSerializerSettings); } - else if (responseMediaType.Contains("xml")) + + if (responseMediaType.Contains("xml")) { XmlSerializer xmlSerializer = new XmlSerializer(type); - using (TextReader reader = new StringReader(response.Content.ReadAsStringAsync().Result)) - { - return xmlSerializer.Deserialize(reader) !; - } - } - else - { - throw new DeserializationException($"Unable to deserialize response with Content-Type '{responseMediaType}'"); + using TextReader reader = new StringReader(responseBodyAsString); + return xmlSerializer.Deserialize(reader); } + + throw new DeserializationException($"Unable to deserialize response with Content-Type '{responseMediaType}'"); + } + + /// + /// Deserializes an body into the specified type. + /// + /// The type to deserialize the response body into. + /// The containing the body to be deserialized. + /// Indicates how to interpret the response content when deserializing. + /// The to use when deserializing to JSON. + /// The deserialized response body object. + /// Thrown when deserialization of the response body fails. + internal static T? DeserializeResponseInto(HttpResponseMessage response, DeserializeAs deserializeAs, JsonSerializerSettings jsonSerializerSettings) + where T : class + { + return DeserializeResponseInto(response, typeof(T), deserializeAs, jsonSerializerSettings) as T; } } -} +} \ No newline at end of file diff --git a/RestAssured.Net/Response/VerifiableResponse.cs b/RestAssured.Net/Response/VerifiableResponse.cs index a0b624c..071c05d 100644 --- a/RestAssured.Net/Response/VerifiableResponse.cs +++ b/RestAssured.Net/Response/VerifiableResponse.cs @@ -718,11 +718,23 @@ public VerifiableResponse UsingJsonSerializerSettings(JsonSerializerSettings jso /// The object type to deserialize into. /// Indicates how to interpret the response content when deserializing. /// The deserialized response object. - public object DeserializeTo(Type type, DeserializeAs deserializeAs = DeserializeAs.UseResponseContentTypeHeaderValue) + public object? DeserializeTo(Type type, DeserializeAs deserializeAs = DeserializeAs.UseResponseContentTypeHeaderValue) { return Deserializer.DeserializeResponseInto(this.Response, type, deserializeAs, this.jsonSerializerSettings); } + /// + /// Deserializes the response content into the specified type and returns it. + /// + /// The type to deserialize the response body into. + /// Indicates how to interpret the response content when deserializing. + /// The deserialized response object. + public T? DeserializeTo(DeserializeAs deserializeAs = DeserializeAs.UseResponseContentTypeHeaderValue) + where T : class + { + return Deserializer.DeserializeResponseInto(this.Response, deserializeAs, this.jsonSerializerSettings); + } + /// /// Logs response details to the standard output. ///