Skip to content

feat: add WithBodyDecoder option for custom JSON body decoding#61

Merged
cubahno merged 2 commits intodoordash-oss:mainfrom
joncanning-rvu:feature/with-body-decoder
Mar 28, 2026
Merged

feat: add WithBodyDecoder option for custom JSON body decoding#61
cubahno merged 2 commits intodoordash-oss:mainfrom
joncanning-rvu:feature/with-body-decoder

Conversation

@joncanning-rvu
Copy link
Copy Markdown
Contributor

@joncanning-rvu joncanning-rvu commented Mar 27, 2026

Summary

Adds a WithBodyDecoder router option that lets consumers customize how JSON request bodies are decoded, following the same functional options pattern as WithErrorHandler and WithMiddleware.

Motivation

The generated adapter calls runtime.DecodeJSONBody directly, with no way to intercept the decoding pipeline. When deserialization fails (e.g., null in a typed array, invalid date formats), the error handler receives a raw Go error with limited context.

A custom body decoder enables:

  • Pre-processing request bodies before decoding (e.g., stripping nulls from arrays)
  • Lenient decoding that tolerates schema mismatches the application wants to handle downstream
  • Error enrichment with application-specific context (e.g., JSON pointer paths)

Changes

  • pkg/runtime/json.go — Added BodyDecoderFunc type: func(body io.Reader, target any) error
  • pkg/codegen/templates/handler/adapter.tmpl — Added bodyDecoder field to HTTPAdapter, defaults to runtime.DecodeJSONBody, calls a.bodyDecoder instead of hardcoded runtime.DecodeJSONBody
  • All 13 router templates — Added bodyDecoder to routerConfig, added WithBodyDecoder option, wired to adapter after construction
  • examples/server/test/server_test.go — Integration tests for the new option

The remaining generated file changes are from make generate.

Backward compatibility

  • NewHTTPAdapter signature is unchanged — still (svc, errHandler)
  • Default behavior is identical — runtime.DecodeJSONBody is used when no custom decoder is set
  • WithBodyDecoder is additive — existing code that doesn't use it is unaffected

Usage

openapi.NewRouter(svc,
    openapi.WithBodyDecoder(func(body io.Reader, target any) error {
        // Custom logic: pre-process, decode, enrich errors
        return runtime.DecodeJSONBody(body, target)
    }),
)

Test plan

  • All existing tests pass (make test)
  • NewHTTPAdapter signature unchanged (no breaking change)
  • All 13 router backends updated consistently
  • Integration tests: custom decoder is invoked, body transformation works

@joncanning-rvu joncanning-rvu force-pushed the feature/with-body-decoder branch from 84d3cd9 to 37cf95b Compare March 27, 2026 13:19
Add a BodyDecoderFunc type and WithBodyDecoder router option that lets
consumers customize how JSON request bodies are decoded. The default
remains runtime.DecodeJSONBody, so this is fully backward-compatible.

Use cases:
- Pre-process request bodies before decoding (e.g. strip nulls)
- Use a lenient decoder that tolerates schema mismatches
- Enrich decode errors with application-specific context

The option follows the same pattern as WithErrorHandler and is
supported across all router backends.
@joncanning-rvu joncanning-rvu force-pushed the feature/with-body-decoder branch from 37cf95b to 5ec4b8f Compare March 27, 2026 13:31
@joncanning-rvu joncanning-rvu marked this pull request as ready for review March 27, 2026 13:39
Copy link
Copy Markdown
Collaborator

@cubahno cubahno left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than renames, looks good, thank you!

Comment thread pkg/runtime/json.go Outdated

// BodyDecoderFunc decodes a request body into the target value.
// The default implementation is DecodeJSONBody.
type BodyDecoderFunc func(body io.Reader, target any) error
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could u plz rename it to JSONBodyDecoderFunc and the With option too because it applies only to json bodies.

Rename all body decoder identifiers to clarify they apply only to JSON:
- BodyDecoderFunc → JSONBodyDecoderFunc
- WithBodyDecoder → WithJSONBodyDecoder
- bodyDecoder field → jsonBodyDecoder

Addresses PR review feedback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@joncanning-rvu joncanning-rvu requested a review from cubahno March 28, 2026 07:50
@cubahno cubahno merged commit 6a09ea5 into doordash-oss:main Mar 28, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants