Skip to content

Commit

Permalink
Merge pull request #787 from tmenier/dev
Browse files Browse the repository at this point in the history
Newtonsoft package updates
  • Loading branch information
tmenier authored Dec 8, 2023
2 parents cc7b511 + ad46151 commit 6dfe74d
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
15 changes: 11 additions & 4 deletions src/Flurl.Http.Newtonsoft/ExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Flurl.Http.Newtonsoft
public static class ExtensionMethods
{
/// <summary>
/// Deserializes JSON-formatted HTTP response body to a dynamic object.
/// Deserializes a JSON-formatted HTTP response body to a dynamic object.
/// </summary>
/// <returns>A Task whose result is a dynamic object containing data in the response body.</returns>
public static async Task<dynamic> GetJsonAsync(this IFlurlResponse resp) {
Expand All @@ -22,7 +22,7 @@ public static async Task<dynamic> GetJsonAsync(this IFlurlResponse resp) {
}

/// <summary>
/// Deserializes JSON-formatted HTTP response body to a list of dynamic objects.
/// Deserializes a JSON-formatted HTTP response body to a list of dynamic objects.
/// </summary>
/// <returns>A Task whose result is a list of dynamic objects containing data in the response body.</returns>
public static async Task<IList<dynamic>> GetJsonListAsync(this IFlurlResponse resp) {
Expand All @@ -31,7 +31,7 @@ public static async Task<IList<dynamic>> GetJsonListAsync(this IFlurlResponse re
}

/// <summary>
/// Deserializes JSON-formatted HTTP response body to a dynamic object. Intended to chain off an async call.
/// Deserializes a JSON-formatted HTTP response body to a dynamic object. Intended to chain off an async call.
/// </summary>
/// <returns>A Task whose result is a dynamic object containing data in the response body.</returns>
public static async Task<dynamic> ReceiveJson(this Task<IFlurlResponse> response) {
Expand All @@ -41,7 +41,7 @@ public static async Task<dynamic> ReceiveJson(this Task<IFlurlResponse> response
}

/// <summary>
/// Deserializes JSON-formatted HTTP response body to a list of dynamic objects. Intended to chain off an async call.
/// Deserializes a JSON-formatted HTTP response body to a list of dynamic objects. Intended to chain off an async call.
/// </summary>
/// <returns>A Task whose result is a list of dynamic objects containing data in the response body.</returns>
public static async Task<IList<dynamic>> ReceiveJsonList(this Task<IFlurlResponse> response) {
Expand All @@ -50,6 +50,13 @@ public static async Task<IList<dynamic>> ReceiveJsonList(this Task<IFlurlRespons
return await resp.GetJsonListAsync().ConfigureAwait(false);
}

/// <summary>
/// Deserializes a JSON-formatted error response body to a dynamic object.
/// </summary>
/// <returns>A Task whose result is a dynamic object containing data in the response body.</returns>
public static async Task<dynamic> GetResponseJsonAsync(this FlurlHttpException flurlException) =>
(flurlException.Call?.Response == null) ? null : await flurlException.Call.Response.GetJsonAsync().ConfigureAwait(false);

/// <summary>
/// Shortcut to use NewtonsoftJsonSerializer with this IFlurlClientBuilder.
/// </summary>
Expand Down
4 changes: 3 additions & 1 deletion src/Flurl.Http.Newtonsoft/Flurl.Http.Newtonsoft.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<LangVersion>9.0</LangVersion>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<PackageId>Flurl.Http.Newtonsoft</PackageId>
<Version>0.9.0-pre2</Version>
<Version>0.9.0-pre3</Version>
<Authors>Todd Menier</Authors>
<Description>A Newtonsoft-based JSON serializer for Flurl.Http 4.0 and above.</Description>
<PackageProjectUrl>https://flurl.dev</PackageProjectUrl>
Expand All @@ -13,6 +13,7 @@
<RepositoryType>git</RepositoryType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageTags>flurl http json</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageReleaseNotes>https://github.com/tmenier/Flurl/releases</PackageReleaseNotes>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
Expand All @@ -26,6 +27,7 @@

<ItemGroup>
<None Include="..\..\icon.png" Pack="true" PackagePath="\" />
<None Include="README.md" Pack="true" PackagePath="\" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<ProjectReference Include="..\Flurl.Http\Flurl.Http.csproj" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
Expand Down
21 changes: 21 additions & 0 deletions src/Flurl.Http.Newtonsoft/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Flurl.Http.Newtonsoft

[![NuGet version (Flurl.Http.Newtonsoft)](https://img.shields.io/nuget/v/Flurl.Http.Newtonsoft.svg?style=flat-square)](https://www.nuget.org/packages/Flurl.Http.Newtonsoft/)

Flurl.Http 4.0 [removed](https://github.com/tmenier/Flurl/issues/517) the `Newtonsoft.Json` dependency in favor of `System.Text.Json` for its default JSON serializer implementation. This has several advantages, most notably that it dramatically reduces Flurl's footprint, which is especially important to developers using it in mobile apps and browser platforms.

But it's also a breaking change. Upgrading from 3.x may cause some pains, such as:

- Newtonsoft's [serialization attributes](https://www.newtonsoft.com/json/help/html/serializationattributes.htm) no longer have any effect, and need be replaced by their STJ equivalents.
- Newtonsoft's [configuration settings](https://www.newtonsoft.com/json/help/html/serializationsettings.htm) also no longer have any effect in Flurl.
- Support for `dynamic`s has also been [removed](https://github.com/tmenier/Flurl/issues/699) in Flurl, specifically due to the lack of support in STJ.

This package aims to solve these problems, making upgrading easier for those who still want or need Newtonsoft-based serialization. Included in this package:

- `NewtonsoftJsonSearializer`, an instance of which can be assigned to a Flurl client or request via `Settings.JsonSerializer`.
- Shortcuts for enabling the serializer more "globally":
- When using the clientless pattern: `FlurlHttp.Clients.UseNewtonsoft()`
- When using DI / [named clients](https://github.com/tmenier/Flurl/issues/770): `new FlurlClientCache().UseNewtonsoft()`
- Non-generic `dynamic`-returning `GetJson`, `GetJsonList`, `ReceiveJson`, and `ReceiveJsonList` extension methods.

Both `NewtonsoftJsonSerializer` and the `UseNewtonsoft` shortcuts take an optional `JsonSerializerSettings` parameter. In fact, the serializer was lifted directly from 3.x, so you can trust that it's battle-tested and highly performant.
28 changes: 28 additions & 0 deletions test/Flurl.Test/Http/NewtonsoftTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using System.Net.Http;
using NUnit.Framework;
using Flurl.Http;
using Flurl.Http.Newtonsoft;
using Flurl.Http.Testing;
using System.Threading.Tasks;
using Flurl.Http.Configuration;
using Newtonsoft.Json;
using NUnit.Framework.Constraints;

namespace Flurl.Test.Http
{
Expand Down Expand Up @@ -55,6 +57,32 @@ public async Task null_response_returns_null_dynamic() {

var list = await resp.ReceiveJsonList();
Assert.IsNull(list);

var ex = new FlurlHttpException(new FlurlCall {
Request = new FlurlRequest(),
HttpRequestMessage = new HttpRequestMessage(),
Response = null,
});
var err = await ex.GetResponseJsonAsync();
Assert.IsNull(err);
}

[TestCase(false)]
[TestCase(true)]
public async Task can_get_error_json_untyped(bool useShortcut) {
HttpTest.RespondWithJson(new { code = 999, message = "our server crashed" }, 500);

try {
await "http://api.com".GetStringAsync();
}
catch (FlurlHttpException ex) {
var error = useShortcut ? // error is a dynamic this time
await ex.GetResponseJsonAsync() :
await ex.Call.Response.GetJsonAsync();
Assert.IsNotNull(error);
Assert.AreEqual(999, error.code);
Assert.AreEqual("our server crashed", error.message);
}
}
}

Expand Down

0 comments on commit 6dfe74d

Please sign in to comment.