Skip to content

feat: respect naming conventions across query, form and JSON body - #2154

Merged
glennawatson merged 2 commits into
mainfrom
fix/issues-batch-1481-1933-1278-2016-1281
Jun 22, 2026
Merged

feat: respect naming conventions across query, form and JSON body#2154
glennawatson merged 2 commits into
mainfrom
fix/issues-batch-1481-1933-1278-2016-1281

Conversation

@glennawatson

Copy link
Copy Markdown
Contributor

What kind of change does this PR introduce?

Feature + bug fix (closes #1481).

What is the new behavior?

First-class, opt-in support for choosing a naming convention that is applied consistently across query keys, form-url-encoded keys, and JSON body property names:

  • New IUrlParameterKeyFormatter implementations: SnakeCaseUrlParameterKeyFormatter (my_property) and KebabCaseUrlParameterKeyFormatter (my-property). CamelCaseUrlParameterKeyFormatter already existed.

  • New RefitSettings presets — RefitSettings.CamelCase(), RefitSettings.SnakeCase(), RefitSettings.KebabCase() — each wires up the matching URL key formatter and a matching JsonNamingPolicy, so query, form, and body all agree:

    var api = RestService.For<IApi>("https://example.com", RefitSettings.SnakeCase());
  • FormValueMultimap now resolves a property's fallback name through UrlParameterKeyFormatter (precedence unchanged: [AliasAs] -> [JsonPropertyName] -> formatter), so form-url-encoded keys honour the configured formatter — the gap behind [Bug]: SystemTextJsonContentSerializer.GetFieldNameForProperty(PropertyInfo) does not use the provided JsonSerializerOptions #1481.

  • The snake/kebab converters and naming policy are TFM-portable (they do not rely on the .NET 8+ built-in policies) and handle acronyms/digits (e.g. JSONParser -> json_parser).

What is the current behavior?

Closes #1481.

What might this PR break?

None. The default UrlParameterKeyFormatter is the identity formatter, so existing form/query behaviour is unchanged. The new behaviour is fully opt-in via a non-default formatter or a preset.

Checklist

  • I have read the Contribute guide
  • Tests have been added or updated (for bug fixes / features)
  • Docs have been added or updated (for bug fixes / features)
  • Changes target the main branch
  • PR title follows Conventional Commits

Additional information

  • New unit tests cover the snake/kebab formatters, the presets (query keys + JSON body naming), and the form-path wiring. The full suite passes and the solution builds clean across all target frameworks.
  • This branch also carries internal groundwork committed separately: aligning the source with the repo's Roslyn analyzers and splitting the Newtonsoft.Json-specific tests into their own assembly. Happy to land that as its own PR if preferred.

…mbly

- Resolve all RoslynCommonAnalyzers/Sonar findings across runtime, the
  source generator, and tests with real fixes (no suppressions): collapse
  branches to conditionals, prefer &&/||/?? over ?: where a side is a
  literal, use switch expressions for #if 3-way returns, target-typed new,
  u8 literals, range/index, inlined out vars, and qualified-name shortening.
- Move every Newtonsoft.Json-specific test out of Refit.Tests into a new
  Refit.Newtonsoft.Json.Tests project; Refit.Tests no longer references
  Refit.Newtonsoft.Json. Shared, non-serializer framework files are linked
  via Compile/Link; Newtonsoft-only helpers are relocated. Dual-serializer
  models are split into STJ and Newtonsoft variants.
- Replace by-name-serialized anonymous payloads with named record types to
  satisfy SST2224 while preserving serialization semantics; keep the
  anonymous-type test anonymous with a single justified suppression.

Full solution builds clean; all test projects pass.
- Add SnakeCaseUrlParameterKeyFormatter and KebabCaseUrlParameterKeyFormatter
  (camelCase already existed), backed by a shared TFM-portable converter
- Add RefitSettings.CamelCase()/SnakeCase()/KebabCase() presets that configure
  query keys, form-url-encoded keys, and JSON body property names consistently
- Route FormValueMultimap's property-name fallback through UrlParameterKeyFormatter
  so form keys honor the configured formatter; the default formatter is identity,
  so existing behavior is unchanged

Addresses #1481 via opt-in presets rather than a breaking default change.
@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.66071% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.54%. Comparing base (3fd4ce6) to head (b4b3689).

Files with missing lines Patch % Lines
src/InterfaceStubGenerator.Shared/Emitter.cs 98.07% 0 Missing and 1 partial ⚠️
...stBuilderImplementation.QueryAndHeaders.Helpers.cs 66.66% 1 Missing ⚠️
src/Refit/StringHelpers.cs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2154      +/-   ##
==========================================
- Coverage   97.63%   97.54%   -0.09%     
==========================================
  Files         110      114       +4     
  Lines        5292     5305      +13     
  Branches      959      959              
==========================================
+ Hits         5167     5175       +8     
- Misses         28       33       +5     
  Partials       97       97              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@glennawatson
glennawatson merged commit 6f2e43d into main Jun 22, 2026
12 of 13 checks passed
@glennawatson
glennawatson deleted the fix/issues-batch-1481-1933-1278-2016-1281 branch June 22, 2026 07:11
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jul 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: SystemTextJsonContentSerializer.GetFieldNameForProperty(PropertyInfo) does not use the provided JsonSerializerOptions

2 participants