Skip to content

Migrate NSwag core to System.Text.Json (v15) - [WIP]#5355

Open
RicoSuter wants to merge 10 commits intov15from
feature/migrate-core-to-stj
Open

Migrate NSwag core to System.Text.Json (v15) - [WIP]#5355
RicoSuter wants to merge 10 commits intov15from
feature/migrate-core-to-stj

Conversation

@RicoSuter
Copy link
Copy Markdown
Owner

No description provided.

Phase 0: Add UseLocalNJsonSchemaProjects switch to Directory.Build.props
and conditional NJsonSchema project/NuGet references to all 6 projects.

Phase 1: Add 5 OpenAPI document serialization snapshot tests using Verify
to lock down behavior before and after migration.

Phase 2: Migrate all 28 NSwag.Core model files from Newtonsoft attributes
to STJ equivalents ([JsonPropertyName], [JsonIgnore], [JsonPropertyOrder]).
Rewrite OpenApiPathItemConverter for STJ. Add EnumMemberStringEnumConverter
for [EnumMember]-aware enum serialization. Add OpenApiParameterJsonConverter
to handle the required bool/array property collision between OpenApiParameter
and JsonSchema. Add parameterless JsonConstructor to OpenApiComponents for
STJ deserialization support.

58/63 NSwag.Core tests pass (4 remaining failures in reference resolution
and external file loading - see docs/plans/findings.md).
- Remove [JsonRequired] from OpenApiOAuthFlow.Scopes (real-world specs
  have OAuth flows without scopes, Newtonsoft was more lenient)
- Update findings.md to reflect 0 remaining failures
- Remove temp debug test
- NSwagDocumentBase: Replace JObject/JToken with JsonNode/JsonObject,
  JsonConvert with JsonSerializer, JsonSerializerSettings with
  JsonSerializerOptions (CamelCase naming, JsonStringEnumConverter)
- 10 command files: mechanical [JsonProperty] → [JsonPropertyName],
  [JsonIgnore] namespace swap, JsonConvert → JsonSerializer
- Core.Yaml: Replace ExpandoObjectConverter with recursive JsonNode
  to ExpandoObject conversion for YamlDotNet compatibility
- AspNetCore: Replace JsonConvert with JsonSerializer in SwaggerUi
  settings and JsonExceptionFilterAttribute, rewrite exception
  serialization without Newtonsoft JsonExceptionConverter
- Remove NJsonSchema.NewtonsoftJson package/project reference
- Replace unused Newtonsoft using with System.Text.Json.Serialization
- Replace JsonConvert.SerializeObject with JsonSerializer.Serialize
- New NSwag.Generation.NewtonsoftJson project with UseNewtonsoftJson()
  extension method and NewtonsoftJsonSettingsResolver for ASP.NET Core
  MvcNewtonsoftJsonOptions detection
- Remove Newtonsoft using from AspNetCoreOpenApiDocumentGenerator,
  deprecate GetJsonSerializerSettings in favor of new package
- Remove last Newtonsoft usings from CodeGeneration projects

Only NSwag.AspNet.WebApi (legacy) and NSwagStudio (WPF) retain
Newtonsoft dependencies. All other NSwag projects are now STJ-only.
…ttings

- Enable UseLocalNJsonSchemaProjects=true in Directory.Build.props
  for development on this branch
- Replace NewtonsoftJsonSchemaGeneratorSettings with
  SystemTextJsonSchemaGeneratorSettings across 26 test files
- Update snapshot files to reflect STJ-based schema generation output
- Remove orphaned Newtonsoft-only test class and its snapshots
- Add JsonElement safety net in CSharpValueGenerator for large specs
@RicoSuter RicoSuter changed the title Migrate NSwag core to System.Text.Json (v15) Migrate NSwag core to System.Text.Json (v15) - [WIP] Apr 5, 2026
…nsoft removal

- Fix null reference in NSwagDocumentBase (lines 181, 518)
- Cache JsonSerializerOptions as static readonly in NSwagDocumentBase
- Add depth limit and try-catch to JsonExceptionFilterAttribute serialization
- Remove hard Newtonsoft dependency from NSwagServiceCollectionExtensions (reflection-based)
- Fix YAML boolean/number type loss (WithAttemptingUnquotedStringTypeDeserialization)
- Migrate YamlDocumentTests from Newtonsoft.Json.Linq to System.Text.Json.Nodes
- Add parameter IsRequired round-trip test and YAML round-trip test
- Add missing NSwag.Generation.NewtonsoftJson reference to AspNetCore.Tests
- Fix QueryParametersTests JToken assertion for STJ
- Bump Namotion.Reflection to 3.5.0
- Add review.md and migration.md, remove findings.md
@RicoSuter RicoSuter changed the base branch from master to v15 April 21, 2026 21:50
@RicoSuter RicoSuter mentioned this pull request Apr 21, 2026
3 tasks
RicoSuter added a commit that referenced this pull request Apr 21, 2026
Pulled from PR #5355 so the v15 integration branch can build against local
NJsonSchema v12 source immediately, validating the sibling-checkout CI setup
end-to-end rather than waiting for the STJ migration PR to land.

- Directory.Build.props: new UseLocalNJsonSchemaProjects property, default true on v15
- 8 csprojs get a pair of conditional ItemGroup blocks (ProjectReference when
  UseLocalNJsonSchemaProjects=true, PackageReference otherwise):
  NSwag.Core, NSwag.Core.Yaml, NSwag.CodeGeneration, NSwag.CodeGeneration.CSharp,
  NSwag.CodeGeneration.TypeScript, NSwag.Generation, NSwag.AspNet.WebApi,
  NSwag.CodeGeneration.Tests

Verified locally: NSwag.Core, NSwag.CodeGeneration.CSharp, and NSwag.Generation
all build clean with ProjectReference resolving to ../NJsonSchema/src/...

Pre-release cleanup updated in plan_v15.md and this change noted in changelog_v15.md.
RicoSuter added a commit that referenced this pull request Apr 21, 2026
* Set up v15 integration branch: plan doc, changelog, CI triggers, sibling NJsonSchema checkout

- Add docs/plan_v15.md describing the v15 scope, dependency on NJsonSchema v12,
  development workflow (UseLocalNJsonSchemaProjects=true), branch model, release
  plan, CI setup, and pre-release cleanup checklist
- Add docs/changelog_v15.md as the running landed-changes log and v14 → v15
  migration guide (starts empty with structural placeholders for planned PR #5355
  and NJsonSchema v12 cascaded changes)
- Add v15 to OnPullRequestBranches / OnPushBranches in build/Build.CI.GitHubActions.cs
  and the regenerated workflow YAMLs
- Hand-edit both workflow YAMLs to clone RicoSuter/NJsonSchema@v12 as a sibling
  directory before build, so project references in UseLocalNJsonSchemaProjects=true
  mode resolve on CI (the clone step will be reverted when NUKE regenerates
  the YAMLs at v15 → master merge time; see cleanup checklist in plan_v15.md)

* Add UseLocalNJsonSchemaProjects mechanism for v15 dev

Pulled from PR #5355 so the v15 integration branch can build against local
NJsonSchema v12 source immediately, validating the sibling-checkout CI setup
end-to-end rather than waiting for the STJ migration PR to land.

- Directory.Build.props: new UseLocalNJsonSchemaProjects property, default true on v15
- 8 csprojs get a pair of conditional ItemGroup blocks (ProjectReference when
  UseLocalNJsonSchemaProjects=true, PackageReference otherwise):
  NSwag.Core, NSwag.Core.Yaml, NSwag.CodeGeneration, NSwag.CodeGeneration.CSharp,
  NSwag.CodeGeneration.TypeScript, NSwag.Generation, NSwag.AspNet.WebApi,
  NSwag.CodeGeneration.Tests

Verified locally: NSwag.Core, NSwag.CodeGeneration.CSharp, and NSwag.Generation
all build clean with ProjectReference resolving to ../NJsonSchema/src/...

Pre-release cleanup updated in plan_v15.md and this change noted in changelog_v15.md.

* Add CLAUDE.md guide for contributor and Claude sessions

- Project Overview: what NSwag is, its distribution channels, NJsonSchema dep
- Cross-check with NJsonSchema: direction of change, when NSwag work needs
  NJsonSchema awareness (extension/overrides, API limitations, spec keyword
  parity, dependency bumping during v15)
- Supported spec targets: Swagger 2.0 / OpenAPI 3.0.x / OpenAPI 3.1, with a
  note that master is 3.0-oriented and v15 completes 3.1 support
- Build and test, high-level architecture by project layer, v15 branch
  conventions, repo-wide settings (TreatWarningsAsErrors, strong-naming,
  artifacts output, ImplicitUsings/LangVersion)
- Code style conventions (analyzer policy, no abbreviations, CRLF, AAA tests)
- Git rule: no AI attribution in commits / PRs / comments

* Pre-build NJsonSchema in Release before NSwag CI build

CI was failing with MSB3030 during NSwag.ConsoleCore publish:
  "Could not copy the file .../NJsonSchema/artifacts/bin/.../release_net8.0/
   NJsonSchema.dll because it was not found."

Root cause: with UseArtifactsOutput=true on both repos, MSBuild's
Configuration=Release property does not reliably propagate across the repo
boundary when NSwag builds NJsonSchema project references transitively.
NJsonSchema ends up compiled to artifacts/bin/*/debug_* while NSwag expects
release_* for the --no-build publish step, so publish fails.

Fix: add an explicit pre-build step after the sibling NJsonSchema clone that
runs 'dotnet build NJsonSchema.sln -c Release' in ../NJsonSchema. The Release
artifacts are then present when NSwag's build invokes dotnet publish --no-build.

Doc updated in plan_v15.md with the rationale.

* Update CLAUDE.md with v15 project documentation and conventions
…o-stj

# Conflicts:
#	Directory.Build.props
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordNewtonsoftJsonSchemaGeneratorTests.When_setting_is_disabled_properties_with_required_attribute_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordNewtonsoftJsonSchemaGeneratorTests.When_setting_is_disabled_properties_with_required_keyword_and_attribute_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordNewtonsoftJsonSchemaGeneratorTests.When_setting_is_disabled_properties_with_required_keyword_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordNewtonsoftJsonSchemaGeneratorTests.When_setting_is_enabled_properties_with_required_attribute_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordNewtonsoftJsonSchemaGeneratorTests.When_setting_is_enabled_properties_with_required_keyword_and_attribute_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordSystemTextJsonSchemaGeneratorSettingsTests.When_setting_is_disabled_properties_with_required_attribute_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordSystemTextJsonSchemaGeneratorSettingsTests.When_setting_is_disabled_properties_with_required_keyword_and_attribute_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordSystemTextJsonSchemaGeneratorSettingsTests.When_setting_is_disabled_properties_with_required_keyword_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordSystemTextJsonSchemaGeneratorSettingsTests.When_setting_is_enabled_properties_with_required_attribute_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp.Tests/Snapshots/UseRequiredKeywordSystemTextJsonSchemaGeneratorSettingsTests.When_setting_is_enabled_properties_with_required_keyword_and_attribute_should_generate_with_required_keyword.verified.txt
#	src/NSwag.CodeGeneration.CSharp/NSwag.CodeGeneration.CSharp.csproj
#	src/NSwag.CodeGeneration.TypeScript/NSwag.CodeGeneration.TypeScript.csproj
#	src/NSwag.CodeGeneration/NSwag.CodeGeneration.csproj
#	src/NSwag.Core.Yaml/NSwag.Core.Yaml.csproj
#	src/NSwag.Core/NSwag.Core.csproj
#	src/NSwag.Generation/NSwag.Generation.csproj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant