Skip to content

query: support struct field name casing options - #192

Open
AdamMagued wants to merge 1 commit into
google:masterfrom
AdamMagued:field-casing-options
Open

AdamMagued wants to merge 1 commit into
google:masterfrom
AdamMagued:field-casing-options

Conversation

@AdamMagued

Copy link
Copy Markdown

Summary

By default, this package uses struct field names directly (which in Go are exported in PascalCase) as the URL parameter names unless overridden by an explicit name in the url struct tag. However, when working with external package structs or generated structs (e.g. protobuf), adding custom struct tags is often not possible, and query parameters typically expect snake_case or camelCase.

This change adds support for struct field name casing options:

  • Adds Case enum (CaseDefault, CaseCamel, CaseSnake, CasePascal, CaseKebab, along with uppercase compatibility aliases).
  • Adds Options struct with an EncodingCase field.
  • Updates Values to accept optional variadic Options (func Values(v interface{}, opts ...Options) (url.Values, error)), maintaining 100% backwards compatibility with existing calls.
  • Adds ValuesWithOptions(v interface{}, opts Options) (url.Values, error).
  • Supports per-field tag options (url:",snake", url:",camel", url:",kebab", url:",pascal").
  • Automatically applies casing recursively to nested and embedded structs when field names are defaulted from the struct definition.

Technical Details

When a field does not specify an explicit parameter name in its tag, reflectValue defaults to sf.Name. Before scoping with any parent prefix, the name is converted using applyCase:

  1. Inspects per-field tag options for casing directives (snake, camel, kebab, pascal).
  2. If no field-level directive is present, checks options.EncodingCase.
  3. If set, splits Go identifier words across boundary transitions (lower/digit to upper, and consecutive uppercase acronyms preceding lowercase words) and formats them into the target casing convention.
    Explicit tag names (e.g. url:"custom_name") are preserved as-is.

Verification Results

  • All existing test cases continue to pass without modification.
  • Added comprehensive unit tests in encode_test.go:
    • TestValues_EncodingCase: verifies CaseDefault, CaseSnake, CaseCamel, CaseKebab, CasePascal, and uppercase aliases across mixed field patterns (IDs, acronyms, numbers, explicit tag overrides).
    • TestValues_TagCasing: verifies per-field tag options (url:",snake", url:",camel", etc.).
    • TestValues_NestedCasing: verifies multi-level nested struct field scoping under casing options.
    • TestValues_EmbeddedCasing: verifies embedded struct field name transformation.
    • TestApplyCase_EdgeCases: tests delimiters, empty inputs, and word formatting helpers.
  • Test coverage remains at 100.0% of statements (go test -v -cover ./... reports 100.0% coverage).
  • Clean gofmt, go vet, and -race execution.

Fixes #86

@google-cla

google-cla Bot commented Oct 1, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Add support for converting struct field names to common casing conventions
(snake_case, camelCase, kebab-case, PascalCase) via Options passed to Values
or ValuesWithOptions, as well as per-field struct tag options (,snake, ,camel,
,kebab, ,pascal).

Fixes google#86

Signed-off-by: AdamMagued <adamismailmageud@gmail.com>
@AdamMagued
AdamMagued force-pushed the field-casing-options branch from 0ce6624 to a9c8b76 Compare October 4, 2026 22:45
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.

Add support for struct field name casing options

1 participant