I've an OpenAPI contract like this:
openapi: 3.0.1
info:
title: Internal API
version: ''
tags:
- name: Calendar
description: Api for Calendar resource
paths:
'/api/v1/appointments/{id}':
get:
tags:
- Calendar
summary: Get the given appointment
description: Get the given appointment
operationId: findById
parameters:
- name: id
in: path
description: The appointment Id
required: true
schema:
type: integer
format: int64
responses:
'200':
description: Successful operation
content:
application/vnd.widget+json:
schema:
$ref: '#/components/schemas/AppointmentWidgetDto'
application/json:
schema:
$ref: '#/components/schemas/Appointment'
components:
schemas:
AppointmentWidgetDto:
required:
- contactEmail
- contactName
- contactPhone
- endDate
- startDate
- store
- title
type: object
properties:
store:
$ref: '#/components/schemas/Store'
title:
maxLength: 255
minLength: 0
type: string
description:
maxLength: 1024
minLength: 0
type: string
type:
maxLength: 50
minLength: 0
type: string
icon:
maxLength: 50
minLength: 0
type: string
startDate:
type: string
format: date-time
endDate:
type: string
format: date-time
contact:
$ref: '#/components/schemas/Contact'
contactName:
type: string
contactEmail:
type: string
contactPhone:
type: string
AuditUser:
type: object
properties:
sid:
type: string
fullName:
type: string
Contact:
required:
- billingCountry
- personType
- preset
- publicAdministration
- shippingCountry
- status
- type
type: object
properties:
id:
type: integer
format: int64
sid:
type: string
createdBy:
$ref: '#/components/schemas/AuditUser'
createdDate:
type: string
format: date-time
lastModifiedDate:
type: string
format: date-time
lastModifiedBy:
$ref: '#/components/schemas/AuditUser'
version:
type: integer
format: int64
userInputTime:
type: integer
format: int64
type:
type: string
enum:
- CUSTOMER
- SUPPLIER
- CUSTOMER_SUPPLIER
- SUBCONTRACTOR
personType:
type: string
enum:
- NATURAL_PERSON
- LEGAL_PERSON
extCode:
maxLength: 50
minLength: 0
type: string
lotteryCode:
maxLength: 8
minLength: 0
type: string
firstName:
type: string
lastName:
type: string
companyName:
type: string
fullName:
type: string
readOnly: true
gender:
type: string
enum:
- MALE
- FEMALE
- OTHER
birthDate:
type: string
format: date
birthCity:
type: string
job:
maxLength: 100
minLength: 0
type: string
billingAddress:
type: string
billingZipCode:
type: string
billingCity:
type: string
billingDistrict:
type: string
billingCountry:
maxLength: 2
minLength: 2
type: string
shippingAddress:
type: string
shippingZipCode:
type: string
shippingCity:
type: string
shippingDistrict:
type: string
shippingCountry:
maxLength: 2
minLength: 2
type: string
taxCode:
type: string
vatNumber:
type: string
landlinePhone:
type: string
mobilePhone:
type: string
fax:
type: string
email:
type: string
certifiedEmail:
type: string
workingDistance:
type: string
enum:
- FAR_NEAR
- INTERMEDIATE_NEAR
- NEAR
- FAR_INTERMEDIATE
bankName:
type: string
iban:
type: string
swift:
type: string
publicAdministration:
type: boolean
sdiAccountId:
type: string
store:
$ref: '#/components/schemas/Store'
preset:
type: boolean
avatar:
type: boolean
status:
type: string
enum:
- ACTIVE
- DECEASED
completenessScore:
type: number
readOnly: true
tags:
type: string
age:
type: integer
format: int32
Store:
required:
- address
- city
- code
- country
- district
- name
- whatsAppEnabled
- zipCode
type: object
properties:
id:
type: integer
format: int64
sid:
type: string
createdBy:
$ref: '#/components/schemas/AuditUser'
createdDate:
type: string
format: date-time
lastModifiedDate:
type: string
format: date-time
lastModifiedBy:
$ref: '#/components/schemas/AuditUser'
version:
type: integer
format: int64
userInputTime:
type: integer
format: int64
name:
type: string
code:
type: string
extCode:
maxLength: 50
minLength: 0
type: string
address:
type: string
zipCode:
type: string
city:
type: string
district:
type: string
country:
maxLength: 2
minLength: 2
type: string
landlinePhone:
type: string
mobilePhone:
type: string
whatsAppEnabled:
type: boolean
fax:
type: string
email:
type: string
certifiedEmail:
type: string
openingHours:
maxLength: 1024
minLength: 0
type: string
contactMinScore:
maximum: 10
minimum: 0
type: number
Agent:
required:
- country
- email
- firstName
- gender
- language
- lastName
- user
- verified
type: object
properties:
id:
type: integer
format: int64
sid:
type: string
createdBy:
$ref: '#/components/schemas/AuditUser'
createdDate:
type: string
format: date-time
lastModifiedDate:
type: string
format: date-time
lastModifiedBy:
$ref: '#/components/schemas/AuditUser'
version:
type: integer
format: int64
userInputTime:
type: integer
format: int64
user:
$ref: '#/components/schemas/User'
firstName:
type: string
lastName:
type: string
gender:
type: string
enum:
- MALE
- FEMALE
- OTHER
color:
maxLength: 30
minLength: 0
type: string
employeeId:
type: string
address:
type: string
zipCode:
type: string
city:
type: string
district:
type: string
country:
maxLength: 2
minLength: 2
type: string
birthDate:
type: string
format: date
taxCode:
type: string
vatNumber:
type: string
landlinePhone:
type: string
mobilePhone:
type: string
email:
type: string
verified:
type: boolean
readOnly: true
language:
maxLength: 2
minLength: 2
type: string
iban:
type: string
swift:
type: string
stores:
uniqueItems: true
type: array
items:
$ref: '#/components/schemas/Store'
avatar:
type: boolean
readOnly: true
tourCompleted:
type: boolean
readOnly: true
enabled:
type: boolean
writeOnly: true
password:
type: string
writeOnly: true
lastPasswordUpdate:
type: string
format: date-time
username:
type: string
roles:
uniqueItems: true
type: array
items:
type: string
enum:
- ROLE_ADMIN
userSid:
type: string
Appointment:
required:
- allDay
- endDate
- startDate
- status
- store
- title
type: object
properties:
id:
type: integer
format: int64
sid:
type: string
createdBy:
$ref: '#/components/schemas/AuditUser'
createdDate:
type: string
format: date-time
lastModifiedDate:
type: string
format: date-time
lastModifiedBy:
$ref: '#/components/schemas/AuditUser'
version:
type: integer
format: int64
userInputTime:
type: integer
format: int64
store:
$ref: '#/components/schemas/Store'
title:
maxLength: 255
minLength: 0
type: string
description:
maxLength: 1024
minLength: 0
type: string
color:
maxLength: 30
minLength: 0
type: string
type:
maxLength: 50
minLength: 0
type: string
icon:
maxLength: 50
minLength: 0
type: string
location:
maxLength: 255
minLength: 0
type: string
startDate:
type: string
format: date-time
endDate:
type: string
format: date-time
allDay:
type: boolean
contact:
$ref: '#/components/schemas/Contact'
contactName:
type: string
contactEmail:
type: string
contactPhone:
type: string
agent:
$ref: '#/components/schemas/Agent'
agentName:
type: string
status:
type: string
readOnly: true
enum:
- TO_APPROVE
- VALID
- CANCELED
- DECLINED
GrantedAuthority:
type: object
properties:
authority:
type: string
User:
required:
- enabled
- fullName
- roles
- username
type: object
properties:
id:
type: integer
format: int64
sid:
type: string
createdBy:
$ref: '#/components/schemas/AuditUser'
createdDate:
type: string
format: date-time
lastModifiedDate:
type: string
format: date-time
lastModifiedBy:
$ref: '#/components/schemas/AuditUser'
version:
type: integer
format: int64
userInputTime:
type: integer
format: int64
fullName:
type: string
username:
maxLength: 255
minLength: 3
type: string
enabled:
type: boolean
readOnly: true
roles:
maxItems: 2147483647
minItems: 1
uniqueItems: true
type: array
items:
type: string
enum:
- ROLE_ADMIN
accountNonExpired:
type: boolean
credentialsNonExpired:
type: boolean
authorities:
type: array
items:
$ref: '#/components/schemas/GrantedAuthority'
accountNonLocked:
type: boolean
I want my endpoint /api/v1/appointments/{id} return 2 different representations of my resource Appointment: the full resource and a light one (with less data).
I thought using content's schema is the right thing to do, so the client can easily decide what it wants.
I tried to generate some clients from this contract using Swagger editor and OpenApi generator but I see these Warning:
[WARNING] Multiple schemas found in the OAS 'content' section, returning only the first one (application/vnd.widget+json)
and my client, as expected from that message, has only one method that returns only 1 representation of the resource.
I found this bug https://github.com/OpenAPITools/openapi-generator/issues/144, but at the same time I think this is a very basic concept of HTTP/REST and I'm bit surpriced it doesn't work. Indeed I'm questioning myself doing something wrong. Is there a way to describe a single endpoint returning different representations of the same resouce (OpenApi contract) generating the client with both methods needed to get the already mentioned resource's representations?