Register default serializers lazily so a custom serializer can replace them without loading System.Text.Json - #2403
Conversation
… them without loading System.Text.Json Fixes restsharp#2402 Co-authored-by: FirmamentalSpring <287222957+FirmaSpring@users.noreply.github.com>
|
PR Summary by QodoLazy-register default serializers so custom JSON serializers avoid loading System.Text.Json
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
1. Duplicated default matching rules
|
| DataFormat.Json, | ||
| ContentType.JsonAccept, | ||
| contentType => contentType.Value.EndsWith("json", StringComparison.InvariantCultureIgnoreCase), | ||
| static () => new SystemTextJsonSerializer() |
There was a problem hiding this comment.
1. Duplicated default matching rules 🐞 Bug ⚙ Maintainability
SerializerConfig.UseDefaultSerializers now hard-codes the default JSON/XML AcceptedContentTypes and SupportsContentType predicates, duplicating logic that already exists on SystemTextJsonSerializer and XmlRestSerializer. This creates a second source of truth, so future changes to serializer matching behavior can silently diverge from the defaults registered in SerializerConfig and lead to inconsistent serializer resolution.
Agent Prompt
## Issue description
`SerializerConfig.UseDefaultSerializers()` duplicates the default serializers' `AcceptedContentTypes` and `SupportsContentType` logic. This increases drift risk: if `SystemTextJsonSerializer` or `XmlRestSerializer` updates its matching rules/content types later, the defaults registered in `SerializerConfig` may no longer match actual serializer behavior.
## Issue Context
The PR intentionally avoids constructing serializers in `UseDefaultSerializers()` to prevent eager loading of `System.Text.Json`. A fix should preserve that laziness while keeping matching metadata in one place.
## Fix approach (keep lazy loading)
- Introduce a shared, dependency-free helper (e.g., internal static class or methods on `ContentType`) that defines:
- `JsonAcceptedContentTypes` / `XmlAcceptedContentTypes` (can just reference `ContentType.JsonAccept` / `ContentType.XmlAccept`), and
- `SupportsJson(ContentType ct)` / `SupportsXml(ContentType ct)` predicates.
- Update both `SerializerConfig.UseDefaultSerializers()` and the serializer classes’ `SupportsContentType` implementations to call the shared helper.
## Fix Focus Areas
- src/RestSharp/Serializers/SerializerConfig.cs[40-55]
- src/RestSharp/Serializers/Json/SystemTextJsonSerializer.cs[39-46]
- src/RestSharp/Serializers/Xml/XmlRestSerializer.cs[23-28]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Problem
RestClientconstructs the defaultSystemTextJsonSerializereagerly inSerializerConfig.UseDefaultSerializers(), before the caller'sconfigureSerializationcallback gets a chance to replace it.For applications that use
RestSharp.Serializers.NewtonsoftJson(or any other custom JSON serializer) exclusively, this forcesSystem.Text.Jsonto be loaded even though it is never used for serialization. On .NET Framework 4.x in shared AppDomain plugin scenarios, this can triggerFileNotFoundExceptionwhen the host has a different strong-namedSystem.Text.Jsonversion bound.Reported in #2402.
Solution
UseDefaultSerializers()now registersSerializerRecordentries that carry a serializer factory (Func<IRestSerializer>) instead of a pre-constructed instance. The serializers are only constructed whenGetSerializer()is first called, so a custom serializer installed viaconfigureSerializationfully replaces the default beforeSystemTextJsonSerializeris ever instantiated.The accepted content types and content type matching functions registered for the defaults mirror the implementations on
SystemTextJsonSerializerandXmlRestSerializer, so serializer resolution behavior is unchanged.Verification
devbranch with a net48 probe that removesSystem.Text.Json.dllfrom the output directory and hooksAssemblyResolve: constructing a client withUseOnlySerializertriggersRESOLVE-FAILED: System.Text.Jsonand exits with code 2.OK: client constructedwithout loading the assembly.RestSharp.Testsnet8.0 serializer filter: 4/4 passed.RestSharp.Tests.Serializers.Jsonnet8.0 full suite: 13/13 passed.Fixes #2402