Skip to main content

Parameters

Documentación

Ya usamos parámetros antes para definir lo que la solicitud debe enviar y validarlos.

Los parámetros pueden ser para:

  • path - Usado junto con Path Templating, donde el valor del parámetro es, en verdad, parte de la URL de la operación. Esto no incluye el host o el camino base de la API. Por ejemplo, en /items/{itemId}, el parámetro path es itemId.
  • query - Parámetros que son anexados a la URL. Por ejemplo, en /items?id=###, el parámetro query es id.
  • header (poco usado) - Encabezados personalizados que son esperados como parte de la solicitud.
  • cookie (poco usado) - Pasa un valor de cookie específico para la API.

Vale la pena saber que existen header y cookie, pero no vamos a enfocarnos en eso pues raramente lo verás y terminarás olvidando rápido. Cuando sea necesario profundiza el estudio en eso.

No confundas query aquí con la query de SQL, no es lo mismo.

¿Qué es obligatorio en cada parámetro?

  • in (string) - El tipo del parámetro y puede ser query, path, header o cookie.
  • name (string, case sensitive) - Necesita ser el mismo nombre utilizado del objeto Path.
  • required (boolean) si el in es path obligatoriamente necesita ser true. Si es los demás puede ser opcional siendo que el default es false.

Tenemos otras cosas que no son obligatorias informar pero pueden ser útiles.

  • description (string) una breve descripción del parámetro.
  • deprecated (boolean) default es false.
  • allowEmptyValue (boolean) y será removido en el futuro.

Podemos tener propiedades adicionales aplicadas a los parámetros en relación a cómo la serialización es hecha, pero también son muy poco utilizadas. Generalmente mantener simples las cosas termina siendo la mejor elección y queda más fácil de mantener. El día que no sea suficiente lo básico busca lo que hay para ayudar.

Query Parameters

Estos son los parámetros que vienen después del path después del ?.

Voy a colocar inicialmente la spec que vamos a trabajar y hacer los comentarios dentro de ella para aprendizaje.

Vamos a especificar 2 parámetros en /v1/customers.

openapi: 3.0.2
info:
####
# Removido para disminuir el código
####
paths:
/v1/customers:
get:
# Al acceder a este path estamos esperando dos parámetros
parameters:
- name: pageNumber
in: query
description: Page number
schema: # ATENCIÓN SOBRE LO QUE VOY A DECIR ALLÁ ABAJO.
type: integer
format: int32
default: 1
# Aquí el required también es false, pero existe un valor default 1
- name: pageSize
in: query
required: false # este ya es el estándar
schema:
type: integer
format: int32
### ...
components:
### ...

El schema no es obligatorio, pero es altamente recomendado. Si omites el schema, la documentación de OpenAPI no tendrá información sobre el tipo de dato esperado para el parámetro, lo que puede confundir a los consumidores de la API. Esto puede generar suposiciones equivocadas, como enviar una string para un parámetro que debería ser un número.

Si fuéramos a consumir este path necesitaríamos pasar algo así https://dev.example.com/v1/customers?pageNumber=5. Si no pasásemos nada https://dev.example.com/v1/customers sería lo mismo que hacer https://dev.example.com/v1/customers?pageNumber=1

Podríamos pasar los dos parámetros https://dev.example.com/v1/customers?pageNumber=4&pageSize=10.

Los parámetros query son separados por &.

alt text

Entonces ahora vamos a mejorar y reaprovechar eso y hacer para beer también, entonces tendríamos esto.

paths:
/v1/customers:
get:
parameters:
- name: pageNumber
in: query
description: Page number
schema:
type: integer
format: int32
default: 1
- name: pageSize
in: query
required: false # este ya es el estándar
schema:
type: integer
format: int32
responses:
200:
description: List of Customers
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerPagedList'
/v1/beers:
get:
parameters:
- name: pageNumber
in: query
description: Page number
schema: # ATENCIÓN SOBRE LO QUE VOY A DECIR ALLÁ ABAJO.
type: integer
format: int32
default: 1
# Aquí el required también es false, pero existe un valor default 1
- name: pageSize
in: query
required: false # este ya es el estándar
schema:
type: integer
format: int32

Ve que tenemos códigos duplicados ahí y podríamos reducir eso. Entonces vamos a utilizar el components!. Ve la spec completa.

openapi: 3.0.2
info:
title: OpenAPI Course
description: Specification for OpenAPI Course
termsOfService: http://example.com/terms/
contact:
name: John Thompson
url: https://springframework.guru
email: [email protected]
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
version: "1.0"
servers:
- url: https://dev.example.com
description: Development Server
- url: https://qa.example.com
description: QA Server
- url: https://prod.example.com
description: Production Server
paths:
/v1/customers:
get:
parameters:
# Este parámetro será el que tenemos en esta referencia al final de la especificación
- $ref: "#/components/parameters/PageNumber"
- $ref: "#/components/parameters/PageSize"
responses:
200:
description: List of Customers
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerPagedList'
/v1/beers:
get:
parameters:
- $ref: "#/components/parameters/PageNumber"
- $ref: "#/components/parameters/PageSize"
responses:
200:
description: List of Beers
content:
application/json:
schema:
$ref: '#/components/schemas/BeerPagedList'
404:
description: No Beers Found
components:
schemas:
Address:
type: object
properties:
line1:
type: string
example: 123 main
city:
type: string
example: St Pete
stateCode:
maxLength: 2
minLength: 2
type: string
description: 2 Letter State Code
enum:
- AL
- AK
- AZ
- AR
- CA
zipCode:
type: string
example: "33701"
Customer:
type: object
properties:
id:
type: string
format: uuid
firstName:
maxLength: 100
minLength: 2
type: string
example: John
lastName:
maxLength: 100
minLength: 2
type: string
example: Thompson
address:
$ref: '#/components/schemas/Address'
description: customer object
CustomerList:
maxItems: 100
minItems: 1
type: array
description: List of Customers
items:
$ref: '#/components/schemas/Customer'
CustomerPagedList:
type: object
properties:
content:
$ref: '#/components/schemas/CustomerList'
allOf:
- $ref: '#/components/schemas/PagedResponse'
Brewery:
type: object
properties:
name:
type: string
location:
type: string
Beer:
type: object
properties:
beerName:
type: string
style:
type: string
enum:
- ALE
- PALE_ALE
- IPA
- WHEAT
- LAGER
price:
type: number
format: float
quantityOnHand:
type: integer
format: int32
brewery:
$ref: '#/components/schemas/Brewery'
description: Beer Object
BeerList:
type: array
items:
$ref: '#/components/schemas/Beer'
BeerPagedList:
type: object
properties:
content:
$ref: '#/components/schemas/BeerList'
allOf:
- $ref: '#/components/schemas/PagedResponse'
PagedResponse:
type: object
properties:
pageable:
$ref: '#/components/schemas/PagedResponse_pageable'
totalPages:
type: integer
format: int32
last:
type: boolean
totalElements:
type: integer
format: int32
size:
type: integer
format: int32
number:
type: integer
format: int32
numberOfElements:
type: integer
format: int32
sort:
$ref: '#/components/schemas/PagedResponse_pageable_sort'
first:
type: boolean
PagedResponse_pageable_sort:
type: object
properties:
sorted:
type: boolean
unsorted:
type: boolean
PagedResponse_pageable:
type: object
properties:
sort:
$ref: '#/components/schemas/PagedResponse_pageable_sort'
offset:
type: integer
format: int32
pageNumber:
type: integer
format: int32
pageSize:
type: integer
format: int32
paged:
type: boolean
unpaged:
type: boolean
############
parameters:
PageNumber: # Convención inicia con mayúscula
# ¡AQUÍ!
name: pageNumber # pero aquí trabajamos iniciando con minúscula
in: query
description: Page number
schema:
type: integer
format: int32
default: 1
PageSize:
name: pageSize
in: query
required: false
schema:
type: integer
format: int32

Es posible sobrescribir lo que importamos del ref.

  /v1/customers:
get:
parameters:
- name: customPageNumber # Nombre sobrescrito aquí
in: query
description: Page number
schema:
type: integer
format: int32
default: 1
- $ref: "#/components/parameters/PageSize" # Aquí, sin sobrescribir
responses:
200:
description: List of Customers
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerPagedList'

Consejo, mantén el mismo en name para no confundir y en caso necesario sobrescribe como mostrado arriba.

Procura mantener un estándar para tus nomenclaturas. Por ejemplo si quisiéramos hacer #/components/parameters/pageSize" podríamos también para saber que ese será el mismo nombre que recibido.

Path Parameters (URL Parameters)

Podemos especificar un recurso dentro de la propia URI definiendo a partir del path. Obviamente que si esa variable hace parte de la URI entonces necesita ser pasado y por eso debe ser required: true.

Los parámetros definidos en el path deben ser indicados dentro de llaves ej: {itemId} y el name del objeto de parámetro debe ser exactamente el mismo

paths:
/v1/customers:
get:
parameters:
- $ref: "#/components/parameters/PageNumber"
- $ref: "#/components/parameters/PageSize"
responses:
200:
description: List of Customers
content:
application/json:
schema:
$ref: '#/components/schemas/CustomerPagedList'
/v1/customers/{customerId}:
get:
parameters:
- name: customerId # Observe que es el mismo nombre
in: path # <<<<
required: true
description: Customer Id
schema:
type: string
# Vamos a utilizar un formateo para esa string utilizando uuid
# uuid es algo así: a48da5c1-9311-44a4-8d2a-bf4eeeb4cf04
format: uuid
responses:
'200':
description: Found Customer
content:
application/json:
schema:
# reaprovechamos el customer no la lista.
$ref: '#/components/schemas/Customer'

alt text

Ahora vamos a mejorar eso y crear para beer también y colocar en el components. En vez de usar beerId y CustomerId vamos a usar solamente ID.

openapi: 3.0.2
info:
#...
paths:
/v1/customers/{Id}:
get:
parameters:
- $ref: '#/components/parameters/Id'
responses:
'200':
description: Found Customer
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'

/v1/beer/{Id}:
get:
parameters:
- $ref: '#/components/parameters/Id' #pero esto traerá el name Id
responses:
'200':
description: Found Beer
content:
application/json:
schema:
$ref: '#/components/schemas/Beer'
components:
schemas:
#...
parameters:
#...
Id:
name: Id
in: path
required: true
description: UUID for Id
schema:
type: string
format: uuid