From 881438d8353bd2072b3050fa84b5266c07c42932 Mon Sep 17 00:00:00 2001 From: MoonsvnLyn <287222957+FirmaSpring@users.noreply.github.com> Date: Mon, 17 Aug 2026 18:25:28 +0800 Subject: [PATCH] Register default serializers lazily so custom serializers can replace them without loading System.Text.Json Fixes #2402 Co-authored-by: FirmamentalSpring <287222957+FirmaSpring@users.noreply.github.com> --- src/RestSharp/Serializers/SerializerConfig.cs | 18 ++++++++++++- .../NewtonsoftJson/IntegratedSimpleTests.cs | 8 ++++++ test/RestSharp.Tests/RestClientTests.cs | 25 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/RestSharp/Serializers/SerializerConfig.cs b/src/RestSharp/Serializers/SerializerConfig.cs index 27055cf12..d8065ecaa 100644 --- a/src/RestSharp/Serializers/SerializerConfig.cs +++ b/src/RestSharp/Serializers/SerializerConfig.cs @@ -37,7 +37,23 @@ public SerializerConfig UseSerializer(Func serializerFactory) { return this; } - public void UseDefaultSerializers() => UseSerializer().UseSerializer(); + public void UseDefaultSerializers() { + // Register factories without constructing the default serializers. Instantiating + // System.Text.Json here would pull it in even when the caller immediately replaces + // JSON with Newtonsoft.Json (or another custom serializer). + Serializers[DataFormat.Json] = new( + DataFormat.Json, + ContentType.JsonAccept, + contentType => contentType.Value.EndsWith("json", StringComparison.InvariantCultureIgnoreCase), + static () => new SystemTextJsonSerializer() + ); + Serializers[DataFormat.Xml] = new( + DataFormat.Xml, + ContentType.XmlAccept, + contentType => contentType.Value.EndsWith("xml", StringComparison.InvariantCultureIgnoreCase), + static () => new XmlRestSerializer() + ); + } /// /// Replace the default serializer with a custom one diff --git a/test/RestSharp.Tests.Serializers.Json/NewtonsoftJson/IntegratedSimpleTests.cs b/test/RestSharp.Tests.Serializers.Json/NewtonsoftJson/IntegratedSimpleTests.cs index 995834822..025b87c2d 100644 --- a/test/RestSharp.Tests.Serializers.Json/NewtonsoftJson/IntegratedSimpleTests.cs +++ b/test/RestSharp.Tests.Serializers.Json/NewtonsoftJson/IntegratedSimpleTests.cs @@ -24,6 +24,14 @@ public async Task Should_serialize_request() { actual.Should().BeEquivalentTo(testData); } + [Fact] + public void UseNewtonsoftJson_replaces_default_json_serializer() { + using var client = new RestClient(_server.Url!, configureSerialization: cfg => cfg.UseNewtonsoftJson()); + + client.Serializers.GetSerializer(DataFormat.Json).Should().BeOfType(); + client.Serializers.Serializers.Should().ContainKey(DataFormat.Xml); + } + [Fact] public async Task Should_deserialize_response() { var expected = Fixture.Create(); diff --git a/test/RestSharp.Tests/RestClientTests.cs b/test/RestSharp.Tests/RestClientTests.cs index 2c82278f1..f8c4067b6 100644 --- a/test/RestSharp.Tests/RestClientTests.cs +++ b/test/RestSharp.Tests/RestClientTests.cs @@ -71,6 +71,31 @@ public void UseOnlySerializer_leaves_only_custom_serializer() { client.Serializers.GetSerializer(DataFormat.Json).Should().NotBeNull(); } + [Fact] + public void Default_serializers_are_registered_lazily_and_survive_replacement() { + // arrange + var baseUrl = new Uri(BaseUrl); + + // act + using var client = new RestClient(baseUrl, configureSerialization: cfg => cfg.UseOnlySerializer(() => new JsonNetSerializerStub())); + + // assert + client.Serializers.Serializers.Should().HaveCount(1); + client.Serializers.GetSerializer(DataFormat.Json).Should().BeOfType(); + } + + sealed class JsonNetSerializerStub : IRestSerializer, ISerializer, IDeserializer { + public string? Serialize(object? obj) => null; + public string? Serialize(Parameter bodyParameter) => null; + public T? Deserialize(RestResponse response) => default; + public ContentType ContentType { get; set; } = ContentType.Json; + public ISerializer Serializer => this; + public IDeserializer Deserializer => this; + public DataFormat DataFormat => DataFormat.Json; + public string[] AcceptedContentTypes => ContentType.JsonAccept; + public SupportsContentType SupportsContentType { get; } = _ => false; + } + [Fact] public void Should_reuse_httpClient_instance() { using var client1 = new RestClient(new Uri("https://fake.api"), useClientFactory: true);