Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making representations a first class concept to address a number of structural concerns #721

Closed
darrelmiller opened this issue Jun 28, 2016 · 16 comments
Assignees

Comments

@darrelmiller
Copy link
Member

darrelmiller commented Jun 28, 2016

This is a proposal to address a number of the issues aggregated under #560.
Specifically:

The basic premise is that OpenAPI models operations that interact with resources using a specific HTTP method. The interaction involves sending representations and retrieving those representations. A single operation may support different representations identified by a media-type.

Consider the following GET operation that returns one of two representations.

get:
  description: Returns pets based on ID
  summary: Find pets by ID
  operationId: getPetsById
  responses:
    '200':
      description: pet response
      representations: 
         application/json:
            schema:
              type: array
              items:
                $ref: '#/definitions/Pet'
         text/html:
    default:
      description: error payload
      representations: 
        application/json:
          schema:
            $ref: '#/definitions/ErrorModel'
        text/html:
parameters:
- name: id
  in: path
  description: ID of pet to use
  required: true
  type: array
  items:
    type: string
  collectionFormat: csv

The description and headers properties of a response object stay, but the schema and examples move under the representation object that is defined as a property of the representations object. The examples property will need to change to either an array of objects, or a single object because all examples would be for the same media type.

By defining the supported media types on the representations object, there is no longer a need for a produces array.

It is important to note that different representations should not be semantically different when accompanied with the same class of status code. A request to a resource should always the same thing (for some unfortunately nebulous definition of thing). However, the syntax of that representation may be different and the amount of information contained may be different, but from a consumer's perspective. it is same concept, regardless of the representation. This is why the description property is the same for all representations.

The following is an example of a POST request that may send a HTML form as a request body.

tags:
- pet
summary: Updates a pet in the store with form data
description: ""
operationId: updatePetWithForm
parameters:
- name: petId
  in: path
  description: ID of pet that needs to be updated
  required: true
  type: string
requestbody:
  description: Updated status of the pet
  required: false
  representations:
    application/x-www-form-urlencoded:
      schema: 
        properties:
          name: 
            description: Updated name of the pet
            type: string
          status:
            description: Updated status of the pet
            type: string
        required: 
          - status
responses:
  '200':
    description: Pet updated.
    representations: 
      application/json:        
      application/xml:
  '405':
    description: Invalid input
    representations:
      application/json:        
      application/xml:    
security:
- petstore_auth:
  - write:pets
  - read:pets

The structure of the HTML form that is passed as a body are no longer intermixed with the URI parameters and are described by a schema object in the representation object. This enables us to support all the different form related media types. There would no longer be any need for the formData parameter type and no need for the consumes array.

One open question is whether there is a value to allowing representation objects (media type, schema and examples) to be defined within the reusable components section.

@ePaul
Copy link
Contributor

ePaul commented Jun 28, 2016

I'm not sure that your text/html part is valid YAML. (I guess this is supposed to be an empty object? Then it should be text/html: {}.)

@darrelmiller
Copy link
Member Author

@ePaul I wasn't sure about that, but I ran it through YAMLLint and it validated ok.

@ePaul
Copy link
Contributor

ePaul commented Jun 28, 2016

And is it parsed as an empty object or an empty array? Or a null?

@wparad
Copy link

wparad commented Jun 28, 2016

Yay +1.

@vrrobz
Copy link

vrrobz commented Jun 28, 2016

Just ran this through with YAMLLint using a format for the content type that includes the profile. It validated it as valid YAML, but only after it reformatted it a bit like so:

requestbody: 
  description: "Updated status of the pet"
  representations: 
    ? "application/json; profile=\"vnd.example.resource.v1\""
    : 
      schema: 
        properties: 
          name: 
            description: "Updated name of the pet"
            type: string
          status: 
            description: "Updated status of the pet"
            type: string
        required: 
          - status
  required: false

I'm not familiar enough with obscure (to me) YAML syntax to know whether it's appropriately treating that as a key for that value. Can someone with more knowledge confirm, please?

@darrelmiller
Copy link
Member Author

@vrrobz The ? is a way of being explicit about something being a key. I don't think there is any ambiguity in our case. http://yaml.org/spec/1.2/spec.html#id2798057

@vrrobz
Copy link

vrrobz commented Jun 28, 2016

Awesome, that's what I needed to know. Thanks!

@DavidBiesack
Copy link

What is the JSON equivalent of yaml ? : notation? (We should be careful to not use YAML specific constructs)

@darrelmiller
Copy link
Member Author

darrelmiller commented Jun 28, 2016

The JSON equivalent to the first example is:

{
  "get": {
    "description": "Returns pets based on ID",
    "summary": "Find pets by ID",
    "operationId": "getPetsById",
    "responses": {
      "200": {
        "description": "pet response",
        "representations" : {
          "application/json" : {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/Pet"
                }
              }
          },
          "text/html" : {} 
        }
      },
      "default": {
        "description": "error payload",
        "representations" : {
          "application/json" : {
              "schema": {
                "$ref": "#/definitions/ErrorModel"
              }
          },
          "text/html" : {}
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "description": "ID of pet to use",
      "required": true,
      "type": "array",
      "items": {
        "type": "string"
      },
      "collectionFormat": "csv"
    }
  ]
}

To my knowledge, I didn't use anything that can't be done in JSON. The : operator in Yaml is just a map, which maps to a JSON object.

@ralfhandl
Copy link
Contributor

For representations in application/xml I'd like to be able to reference an XML Schema.

@darrelmiller
Copy link
Member Author

@ralfhandl I agree. Supporting different schemas like XML Schema, Relax NG, Schematron, and alternative JSON validation like JCR seems like a ideal goal to me.

The challenge is that we would need to find a way to decouple the OpenAPI description mechanisms from the schema validation process. The benefit is that OpenAPI tooling would not have to reinvent schema validation mechanisms. But, tooling would have to deal with the fact that it might run into a validation mechanism that it doesn't know how to process.

@ralfhandl
Copy link
Contributor

In #333 a schemaType or schemaLanguage property was proposed to describe the type/language used in the schema property. The default/fallback could be the OpenAPI subset of JSON Schema.

That way tools can skip schemas whose language they can't cope with.

@fehguy
Copy link
Contributor

fehguy commented Jul 22, 2016

representing the schema for non-JSON structures is something we'll tackle outside of this PR. but I do think that this fixes the association between the content format and consumes and produces, by coupling them together. So +1 to this.

@fehguy
Copy link
Contributor

fehguy commented Jul 22, 2016

Will turn this into a PR for both the input (requestBody) parameter, and for response representations. We will keep the parameter serialization outside of the scope of the PR.

@fehguy
Copy link
Contributor

fehguy commented Jul 22, 2016

consider having examples: [] as a sibling to schema in the representation object.

@webron
Copy link
Member

webron commented Mar 3, 2017

This has been implemented in 3.0.0-RC0! 🎉

@webron webron closed this as completed Mar 3, 2017
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

No branches or pull requests

8 participants