Imagine you have the object User (see below) which is used to specify the body param in both the calls Post /users and Patch /users/:id.
I want to use it for both API calls, but I need to specify that firstname and lastname are not required in the Patch call.
I know I could do that by duplicating the file user.yaml into another file (maybe called patch_user.yml) and removing the required section:
required:
- firstname
- lastname
but I was wondering if there is a better way. I have the same issue in many endpoints, and I would end up with lots of duplication.
How would you tackle this problem?
user.yaml:
User
type: object
required:
- type
- attributes
properties:
id:
type: string
type:
type: string
attributes:
type: object
required:
- firstname
- lastname
properties:
firstname:
type: string
example: John
lastname:
type: string
example: Doe
Related
I need inheritance only with one field in super class, so propertyName is no need. Is anyway to ignore propertyName?
Base:
type: object
discriminator:
propertyName: useless
required:
- id
properties:
id:
type: integer
format: int64
example: 1
Response like
"useless":"subtype", "id":1
And throws error like
Unrecognized field "useless"
I need inheritance only with id, without field propertyName, is anyway to do it?
Or make propertyName as integer id?
Given the following OpenAPI YAML, do we always need to define petType while creating Pet?
Can I by default create a pet of type Dog without specifying petType? Is there some way to do this with OpenAPI?
Pet:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
discriminator:
propertyName: petType
do we always need to define petType while creating Pet
Yes. As explained in the Discriminator Object section of the OpenAPI Specification (emphasis mine):
a discriminator MAY act as a "hint" to ... selection of the matching schema ... We can then describe exactly which field tells us which schema to use:
...
The expectation now is that a property with name petType MUST be present in ... payload, and the value will correspond to the name of a schema defined in the OAS document.
I had a similar problem myself, and I was able to work out the following solution:
Pet:
x-field-extra-annotation: '#com.fasterxml.jackson.annotation.JsonTypeInfo(
use = com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME,
include = com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY,
property = "petType", visible = true,
defaultImpl = Dog.class)'
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Lizard'
discriminator:
propertyName: petType
I used 6.0.1 version of the OpenAPI generator.
Just in case, here is the link to the documentation where I found many other helpful solutions:
https://openapi-generator.tech/docs/generators/spring
How would you deal with interfaces and using them for connections in a data model using the AWS Amplify Model Transforms?
interface User #model {
id: ID
email: String
created: AWSTimestamp
}
type ActiveUser implements User {
id: ID
first: String
last: String
email: String
created: AWSTimestamp
}
type InvitedUser implements User {
id: ID
email: String
created: AWSTimestamp
invitedBy: String
}
type Team #model {
users: [User] #connection
}
It seems like my choices are to put #model on the types but then I get separate Dynamo tables and queries on the Query once amplify update api is run.
Can the transformer support interfaces as documented here: https://docs.aws.amazon.com/appsync/latest/devguide/interfaces-and-unions.html
I also found some support tickets, but was wondering if there was anything out there that enabled this feature. Here are the support tickets I found:
https://github.com/aws-amplify/amplify-cli/issues/1037
https://github.com/aws-amplify/amplify-cli/issues/202
You only use #connection to link two databases together (which must be made from type and not interface), so if you don't want to do that then just get rid of the #connection and the Team database will simply have users be of type [User]. I am not entirely what you want to do but I would do something like:
type User #model {
id: ID
first: String!
last: String!
email: String!
created: AWSTimestamp
isActive: boolean
invitedBy: String
team: Team #connection(name: "UserTeamLink")
}
type Team #model {
users: [User!] #connection(name: "UserTeamLink")
}
Where the fields first, last, and email are required when creating a new user, and you can distinguish between an active user with a boolean, and when you query the User database it returns the Team item from the Team database as well (I am guessing you want other fields like team name, etc.?), so when you create a Team object you pass in the teamUserId (not shown below but created when using amplify) that will allow you to attach a newly created Team to an existing user or group of users.
I think you could keep the common fields in User, and extra info in separate type. Not sure if this is the best practice, but it should work for this scenario
enum UserType {
ACTIVE
INVITED
}
type User #model #key(name:"byTeam", fields:["teamID"]){
id: ID!
teamID: ID!
email: String
created: AWSTimestamp
type: UserType
activeUserInfo: ActiveUserInfo #connection(fields:["id"])
invitedUserInfo: InvitedUserInfo #connection(fields:["id"])
}
type ActiveUserInfo #key(fields:["userID"]){
userID: ID!
first: String
last: String
}
type InvitedUserInfo #key(fields:["userID"]){
userID: ID!
invitedBy: String
}
type Team #model {
id:ID!
users: [User!] #connection(keyName:"byTeam", fields:["id"])
}
When I use a Dto in the models of the api documentation, the name of the Dto is documented as follows, Customer: 01d691680190c1b19dfee75af0f2e292, it is possible to customize this name to Customer: Input or anything else.
This is the configuration of my resource:
App\Entity\Customer\Customer:
collectionOperations:
register:
method: POST
path: /register
controller: App\Controller\ShopApi\Customer\RegisterCustomerAction
input:
class: App\Dto\RegisterCustomerRequest
name: RegisterCustomerRequest
itemOperations:
get:
normalization_context:
jsonld_embed_context: true
groups: ['customer:read']
swagger_definition_name: CustomerResponse
But then in the api doc I get as a model:
Customer:01d691680190c1b19dfee75af0f2e292 {
email* string
plainPassword* string
firstName* string
lastName* string
gender* string
identificationNumber* string
typeIdentificationNumber* string
subscribedToNewsletter boolean
confirmTermsConditions boolean
addressAlias string
address* string
countryCode* string
provinceCode string
provinceName string
city* string
postcode* string
phoneNumber* string }
Problem
I'm trying to describe an API which is supposed to have resources PATCH methods work like described in RFC 7396.
Basically a POST method have a set of properties in it's body, some required some not.
PATCH (by some standards) has no fields required - requests body contains only the fields you want to update, additionally the API allows a client to "clean" a field by sending a null.
Example:
#%RAML 1.0
title: test
mediaType: [application/json]
types:
Create:
type: object
properties:
description: string
Retrieve:
type: Create
properties:
id: string
Update:
type: object
properties:
description?: nil | string
/resource:
get:
responses:
200:
body:
type: Retrieve[]
post:
body:
type: Create
/{id}:
uriParameters:
id: string
get:
responses:
200:
body:
type: Retrieve
patch:
body:
type: Update
responses:
200:
body:
type: Retrieve
in the example I have a Update type specified just for that task, because... Create has a required description, Retrieve inherits from Create as it should return all it's fields and the additional id, Update can't inherit from Create as RAML does not allow to override a required field with one that is not required.
Questions:
Is there a better way to describe that API?
If not is nil | string the proper way to go when writing that Update type "from scratch"?
I don't think there's a better way. Only thing is, if you have not required properties in both the create and the update, then you could create a base type.
Yes, nil | [type] is the way to go. You need to be able to "clean" the property by sending null.