Skip to content

Commit

Permalink
Update "format" and "content*" for new JSON Schema (#2200)
Browse files Browse the repository at this point in the history
* Update "format" and "content*" for new JSON Schema

This removes OAS formats and examples that are now superfluous
as they are part of the 2019-09 JSON Schema draft.

Similarly it deprecates the "byte" and "binary" formats in favor
of JSON Schema's "contentEncoding" and "contentMediaType" keywords,
and updates various related exapmles and other guidance.

It also removes confusingly blank rows in the OAS format table.

* "format" is an annotation

* Fix broken table, type, in Encoding Object

Broke some things while updating for "content*"

* Fix format of `format`

Backticks, not double quotes.

* Remove unneeded detail on "format"

This was just duplicating info from the JSON Schema spec.

Co-authored-by: Darrel <darrmi@microsoft.com>

* Remove "byte" and "binary" formats altogether.

Instead of just deprecating.  The "content*" keywords now
cover these use cases.

* Harmonize JSON Schema content* + Media Type Object

Includes harmonizing with the Encoding Object.  In general,
OpenAPI objects set the media type, although there is a case
for `contentMediaType` with multipart/form-data.  Otherwise,
`contentEncoding` replaces the now-removed custom formats.

A possibly controversial change is to indicate unencoded binary
data by omitting `type` (or omitting the schema altogether), as
binary data does not conform to JSON string requirements.

This could still be done with `type: string` if that is preferred.
It's going to be a bit weird either way.

I can add wording in the next JSON Schema draft to clarify
whichever approach makes more sense.

* Fix typos from review

* Remove stray {}

* Fix inconsistencies contentMediaType and Encoding Object

Co-authored-by: Darrel <darrmi@microsoft.com>
  • Loading branch information
handrews and darrelmiller authored May 28, 2020
1 parent ece5497 commit 69662e4
Showing 1 changed file with 42 additions and 43 deletions.
85 changes: 42 additions & 43 deletions versions/3.1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,14 @@ Primitive data types in the OAS are based on the types supported by the [JSON Sc
Note that `integer` as a type is also supported and is defined as a JSON number without a fraction or exponent part.
Models are defined using the [Schema Object](#schemaObject), which is a superset of JSON Schema Specification Draft 2019-09.

<a name="dataTypeFormat"></a>Primitives have an optional modifier property: `format`.
OAS uses several known formats to define in fine detail the data type being used.
<a name="dataTypeFormat"></a>Primitives have an optional modifier property: `format`, which is defined by JSON Schema.
OAS uses several known additional formats to define in fine detail the data type being used.
However, to support documentation needs, the `format` property is an open `string`-valued property, and can have any value.
Formats such as `"email"`, `"uuid"`, and so on, MAY be used even though undefined by this specification.
Additional formats MAY be used even though undefined by either JSON Schema or this specification.
Types that are not accompanied by a `format` property follow the type definition in the JSON Schema. Tools that do not recognize a specific `format` MAY default back to the `type` alone, as if the `format` is not specified.

Note that by default, JSON Schema validators will not attempt to validate the `format` keyword. https://json-schema.org/draft/2019-09/release-notes.html#format-vocabulary

The formats defined by the OAS are:

[`type`](#dataTypes) | [`format`](#dataTypeFormat) | Comments
Expand All @@ -161,15 +163,8 @@ The formats defined by the OAS are:
`integer` | `int64` | signed 64 bits (a.k.a long)
`number` | `float` | |
`number` | `double` | |
`string` | | |
`string` | `byte` | base64 encoded characters
`string` | `binary` | any sequence of octets
`boolean` | | |
`string` | `date` | As defined by `full-date` - [RFC3339](https://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14)
`string` | `date-time` | As defined by `date-time` - [RFC3339](https://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14)
`string` | `password` | A hint to UIs to obscure input.


### <a name="richText"></a>Rich Text Formatting
Throughout the specification `description` fields are noted as supporting CommonMark markdown formatting.
Where OpenAPI tooling renders rich text it MUST support, at a minimum, markdown syntax as described by [CommonMark 0.27](https://spec.commonmark.org/0.27/). Tooling MAY choose to ignore some CommonMark features to address security concerns.
Expand Down Expand Up @@ -1447,20 +1442,35 @@ application/json:

##### Considerations for File Uploads

In contrast with the 2.0 specification, `file` input/output content in OpenAPI is described with the same semantics as any other schema type. Specifically:
In contrast with the 2.0 specification, `file` input/output content in OpenAPI is described with the same semantics as any other schema type. In contrast with the 3.0 specification, such schemas use the `contentEncoding` JSON Schema keyword rather than the `format` keyword. This keyword supports all encodings defined in [RFC4648](https://tools.ietf.org/html/rfc4648), including "base64" and "base64url", as well as "quoted-printable" from [RFC2045](https://tools.ietf.org/html/rfc2045#section-6.7).

JSON Schema also offers a `contentMediaType` keyword. However, when the media type is already specified by the
Media Type Object's key, or by the `contentType` field of an [Encoding Object](#encodingObject), the `contentMediaType` keyword SHALL be ignored if present.

Examples:

Content transferred in binary (octet-stream) SHOULD omit `schema`, as no JSON Schema type is suitable:

```yaml
# content transferred with base64 encoding
schema:
type: string
format: base64
# a PNG image as a binary file:
content:
image/png: {}
```

```yaml
# content transferred in binary (octet-stream):
schema:
type: string
format: binary
# an arbitrary binary file:
content:
application/octet-stream: {}
```

Binary content transferred with base64 encoding:

```yaml
content:
image/png:
schema:
type: string
contentEncoding: base64
```

These examples apply to either input payloads of file uploads or response payloads.
Expand All @@ -1470,11 +1480,7 @@ A `requestBody` for submitting a file in a `POST` operation may look like the fo
```yaml
requestBody:
content:
application/octet-stream:
schema:
# a binary file of any type
type: string
format: binary
application/octet-stream: {}
```

In addition, specific media types MAY be specified:
Expand All @@ -1484,14 +1490,8 @@ In addition, specific media types MAY be specified:
requestBody:
content:
# a binary file of type png or jpeg
'image/jpeg':
schema:
type: string
format: binary
'image/png':
schema:
type: string
format: binary
image/jpeg: {}
image/png: {}
```

To upload multiple files, a `multipart` media type MUST be used:
Expand All @@ -1506,9 +1506,7 @@ requestBody:
file:
type: array
items:
type: string
format: binary
contentMediaType: application/octet-stream
```

##### Support for x-www-form-urlencoded Request Bodies
Expand Down Expand Up @@ -1546,8 +1544,10 @@ When passing in `multipart` types, boundaries MAY be used to separate sections o

* If the property is a primitive, or an array of primitive values, the default Content-Type is `text/plain`
* If the property is complex, or an array of complex values, the default Content-Type is `application/json`
* If the property is a `type: string` with `format: binary` or `format: base64` (aka a file object), the default Content-Type is `application/octet-stream`
* If the property is a `type: string` with a `contentEncoding`, the default Content-Type is `application/octet-stream`
* If the JSON Schema keyword `contentMediaType` is used and no Encoding Object is present, then the Content-Type is that which is specified by `contentMediaType`, however if an Encoding Object is present, then `contentMediaType` SHALL be ignored

As with non-multipart request or response bodies, when using `contentMediaType` to specify a binary Content-Type without also using `contentEncoding`, the JSON Schema `type` keyword is omitted.

Examples:

Expand All @@ -1566,9 +1566,8 @@ requestBody:
type: object
properties: {}
profileImage:
# default Content-Type for string/binary is `application/octet-stream`
type: string
format: binary
# Content-Type with contentMediaType is the contentMediaType (image/png here)
contentMediaType: image/png
children:
# default Content-Type for arrays is based on the `inner` type (text/plain here)
type: array
Expand All @@ -1578,7 +1577,8 @@ requestBody:
# default Content-Type for arrays is based on the `inner` type (object shown, so `application/json` in this example)
type: array
items:
type: '#/components/schemas/Address'
type: object
$ref: '#/components/schemas/Address'
```
An `encoding` attribute is introduced to give you control over the serialization of parts of `multipart` request bodies. This attribute is _only_ applicable to `multipart` and `application/x-www-form-urlencoded` request bodies.
Expand All @@ -1590,7 +1590,7 @@ A single encoding definition applied to a single schema property.
##### Fixed Fields
Field Name | Type | Description
---|:---:|---
<a name="encodingContentType"></a>contentType | `string` | The Content-Type for encoding a specific property. Default value depends on the property type: for `string` with `format` being `binary` – `application/octet-stream`; for other primitive types – `text/plain`; for `object` - `application/json`; for `array` – the default is defined based on the inner type. The value can be a specific media type (e.g. `application/json`), a wildcard media type (e.g. `image/*`), or a comma-separated list of the two types.
<a name="encodingContentType"></a>contentType | `string` | The Content-Type for encoding a specific property. Default value depends on the property type: when `type` is absent and `contentMediaType` is present - the value of `contentMediaType`; when both `type` and `contentMediaType` are absent - `application/octet-stream`; for `string` with a `contentEncoding` - `application/octet-string`; for other primitive types – `text/plain`; for `object` - `application/json`; for `array` – the default is defined based on the inner type. The value can be a specific media type (e.g. `application/json`), a wildcard media type (e.g. `image/*`), or a comma-separated list of the two types.
<a name="encodingHeaders"></a>headers | Map[`string`, [Header Object](#headerObject) \| [Reference Object](#referenceObject)] | A map allowing additional information to be provided as headers, for example `Content-Disposition`. `Content-Type` is described separately and SHALL be ignored in this section. This property SHALL be ignored if the request body media type is not a `multipart`.
<a name="encodingStyle"></a>style | `string` | Describes how a specific property value will be serialized depending on its type. See [Parameter Object](#parameterObject) for details on the [`style`](#parameterStyle) property. The behavior follows the same values as `query` parameters, including default values. This property SHALL be ignored if the request body media type is not `application/x-www-form-urlencoded` or `multipart/form-data`. If a value is explicitly defined, then the value of [`contentType`](#encodingContentType) (implicit or explicit) SHALL be ignored.
<a name="encodingExplode"></a>explode | `boolean` | When this is true, property values of type `array` or `object` generate separate parameters for each value of the array, or key-value-pair of the map. For other types of properties this property has no effect. When [`style`](#encodingStyle) is `form`, the default value is `true`. For all other styles, the default value is `false`. This property SHALL be ignored if the request body media type is not `application/x-www-form-urlencoded` or `multipart/form-data`. If a value is explicitly defined, then the value of [`contentType`](#encodingContentType) (implicit or explicit) SHALL be ignored.
Expand Down Expand Up @@ -1621,9 +1621,8 @@ requestBody:
type: object
properties: {}
profileImage:
# default is application/octet-stream, need to declare an image type only!
type: string
format: binary
contentMediaType: image/jpeg
encoding:
historyMetadata:
# require XML Content-Type in utf-8 encoding
Expand Down

0 comments on commit 69662e4

Please sign in to comment.