Skip to content

Commit

Permalink
Merge pull request #350 from danielgtaylor/json-raw-message
Browse files Browse the repository at this point in the history
feat: support json.RawMessage
  • Loading branch information
danielgtaylor authored Apr 2, 2024
2 parents 73362ec + bb72a27 commit 85d94d8
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 5 deletions.
17 changes: 15 additions & 2 deletions docs/docs/features/request-inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ The special struct field `Body` will be treated as the input request body and ca

`RawBody []byte` can also be used alongside `Body` to provide access to the `[]byte` used to validate & parse `Body`.

### Special Types

The following special types are supported out of the box:

| Type | Schema | Example |
| ----------------- | ------------------------------------------- | ----------------------------- |
| `time.Time` | `{"type": "string", "format": "date-time"}` | `"2020-01-01T12:00:00Z"` |
| `url.URL` | `{"type": "string", "format": "uri"}` | `"https://example.com"` |
| `net.IP` | `{"type": "string", "format": "ipv4"}` | `"127.0.0.1"` |
| `json.RawMessage` | `{}` | `["whatever", "you", "want"]` |

You can override this default behavior if needed as described in [Schema Customization](./schema-customization.md) and [Request Validation](./request-validation.md), e.g. setting a custom `format` tag for IPv6.

### Other Body Types

Sometimes, you want to bypass the normal body parsing and instead read the raw body contents directly. This is useful for unstructured data, file uploads, or other binary data. You can use `RawBody []byte` **without** a `Body` field to access the raw body bytes without any parsing/validation being applied. For example, to accept some `text/plain` input:
Expand All @@ -78,9 +91,9 @@ This enables you to also do your own parsing of the input, if needed.

### Multipart Form Data

Multipart form data is supported by using a `RawBody` with a type of
Multipart form data is supported by using a `RawBody` with a type of
`multipart.Form` type in the input struct. This will parse the request using
Go standard library multipart processing implementation.
Go standard library multipart processing implementation.

For example:

Expand Down
9 changes: 6 additions & 3 deletions schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ const (

// Special JSON Schema formats.
var (
timeType = reflect.TypeOf(time.Time{})
ipType = reflect.TypeOf(net.IP{})
urlType = reflect.TypeOf(url.URL{})
timeType = reflect.TypeOf(time.Time{})
ipType = reflect.TypeOf(net.IP{})
urlType = reflect.TypeOf(url.URL{})
rawMessageType = reflect.TypeOf(json.RawMessage{})
)

func deref(t reflect.Type) reflect.Type {
Expand Down Expand Up @@ -597,6 +598,8 @@ func SchemaFromType(r Registry, t reflect.Type) *Schema {
return &Schema{Type: TypeString, Format: "uri"}
case ipType:
return &Schema{Type: TypeString, Format: "ipv4"}
case rawMessageType:
return &Schema{}
}

minZero := 0.0
Expand Down
5 changes: 5 additions & 0 deletions schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ func TestSchema(t *testing.T) {
input: net.IPv4(127, 0, 0, 1),
expected: `{"type": "string", "format": "ipv4"}`,
},
{
name: "json.RawMessage",
input: &json.RawMessage{},
expected: `{}`,
},
{
name: "bytes",
input: []byte("test"),
Expand Down
7 changes: 7 additions & 0 deletions validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,13 @@ var validateTests = []struct {
},
errs: []string{"expected object with at most 1 properties"},
},
{
name: "json.RawMessage success",
typ: reflect.TypeOf(struct {
Value json.RawMessage `json:"value"`
}{}),
input: map[string]any{"value": map[string]any{"some": []any{"thing"}}},
},
{
name: "object struct success",
typ: reflect.TypeOf(struct{}{}),
Expand Down

0 comments on commit 85d94d8

Please sign in to comment.