How to define data type for Expand API in RAML - api

I am designing an API operation and am going to use the expand standard.
Here is an example of my first API response....
{
"id": "000000001",
"createdDateTime": "2017-12-19T16:39:57-08:00",
"lastUpdatedDateTime": "2017-12-19T16:45:57-08:00",
"holdingDetails": {
"status": "SUCCESSFUL",
"instrument": "/api/v1//instruments/123456789"
}
}
Here is an example of my second API response....
{
"id": "000000001",
"createdDateTime": "2017-12-19T16:39:57-08:00",
"lastUpdatedDateTime": "2017-12-19T16:45:57-08:00",
"holdingDetails": {
"status": "SUCCESSFUL",
"instrument": {
"instrumentId":"123456789",
"nickName":"My NickName",
"type": "BLAH"
}
}
}
In my raml I would like to define a type for this i'm not sure what is would look like...
#%RAML 1.0 DataType
type: object
properties:
id?:
type: string
createdDateTime?:
type: datetime
lastUpdatedDateTime?:
type: datetime
What goes next? i.e. How do I say it can be either listed below
instrument?:
type: string
description: A link to the instrument
instrument?:
type: !include instrument.raml

You can use an union
e.g.:
instrument?:
type: string | InstrumentType
and of course also define InstrumentType, for example with something like this:
InstrumentType:
properties:
instrumentId:
nickName:
type:

Related

how to define type Date in jsonSchemaType?

I have an interface (using typescript) that I am building a Json schema for.
export interface IMyDate{
FromDateUtc: Date,
ToDateUtc: Date
}
this is how I defined the schema:
JSONSchemaType<IMyDate> = {
type: "object",
properties: {
FromDateUtc: {
type: "string",
format: "date-time",
},
ToDateUtc: {
type: "string",
format: "date-time",
},
required: [
"FromDateUtc",
"ToDateUtc",
],
additionalProperties: false,
};
I am getting this error:
The types of 'properties.FromDateUtc' are incompatible between these types.
Type '{ type: "string"; format: string; }' is not assignable to type '{ $ref: string; } | (UncheckedJSONSchemaType<Date, false> & { const?: Date | undefined; enum?: readonly Date[] | undefined; default?: Date | undefined; })'.
Any ideas why and how I can fix this?
In json-schema-to-typescript, We can use the tsType property in our JSON schema to override the type. tsType Overrides the type that's generated from the schema. Helpful in forcing a type to any or when using non-standard JSON schema extensions.
For Example, the JSON schema given below generates a type birthday with date as it's type.
const birthday = {
name: `birthday `,
type: `string`,
tsType: `Date`,
format: `date-time`,
}
export type birthday = Date;
date-time:
A string instance is valid against this attribute if it is a valid representation according to the "date-time' ABNF rule
From json-schema-validation spec
So the string might be valid against this format but it is still a string.
Try this:
export interface IMyDate {
FromDateUtc: string;
ToDateUtc: string;
}
According to JSON Schema Online Validator, the following is a valid JSON Schema:
{
"title": "IMyDate",
"type": "object",
"properties": {
"FromDateUtc": {
"type": "string",
"format": "date-time"
},
"ToDateUtc": {
"type": "string",
"format": "date-time"
},
"required": [
"FromDateUtc",
"ToDateUtc"
],
"additionalProperties": false
}
}
You could now use json-schema-to-typescript
to extract the interface. The documentation of this tool states that format is "not expressible in TypeScript" and therefore the generated interface is the same as given above (with attributes of type string).
Note that there are several ways to convert a Date into a properly fomatted string.

Fastify and json schema validation

I'm trying to learn fastify throught the official documentation. I'm really intrested in the validation of an incoming post request with a json schema. Following the instructions i added to my routes:
fastify.addSchema({
$id: 'http://example.com/',
type: 'object',
properties: {
hello: { type: 'string' }
}
})
fastify.post('/', {
handler() { },
schema: {
body: {
type: 'array',
items: { $ref: 'http://example.com#/properties/hello' }
}
}
})
Now the problem is that I can not write a json that can be accepted by this schema. From my basic understanding a simple post request like the following should be accepted
[
{
"hello": "bye"
},
{
"hello": "bye bye"
}
]
However server keeps telling me that body[0] should be string. Where am I wrong?
The reference $ref: 'http://example.com#/properties/hello' points to the hello property schema value, which is { type: 'string' }.
This means the schema in fastify.post('/', { expects the body to be an array of strings.

RAML: using same data type for GET & POST with differing properties

So I'm extracting a JSON schema out of my RAML spec to validate output in GET methods and also the input in the POST method.
Every entity of this type has a "required" ID property - at least it's required when listing those entities in a 'get item' or 'get collection'-request.
But when validating the received post data to create such an entity the ID is obviously not required (and discarded if it's send anyway).
What's the best DRY way to have this ID property required for GET requests, but not required, or even better not existing in the type for POST requests?
TL;DR: start reading below ;)
Example to make it easier to understand:
For GET requests the type should be like:
properties:
id:
something1:
something2?:
For POST requests the type should be like:
properties:
something1:
something2?:
without having to define both separately, but also without using inheritance to have to create two types for every resource.
Ideally I would solve it that way, but that doesn't seem to work:
get:
description: Retrieve a list of <<resourcePathName|!uppercamelcase>>.
responses:
200:
body:
application/json:
type: [ entity_id_object, <<resourcePathName|!singularize|!uppercamelcase>> ][]
example: <<exampleCollection>>
and entity_id_object ist just:
entity_id_object:
properties:
id:
I think it's because the <<resourcePathName|!singularize|!uppercamelcase>> is not working in this combination.
I can't think of a way of doing it without two types yet. But this example at least only makes you only pass one type and automatically appends 'NoId' to the type name for POST requests.
#%RAML 1.0
title: My API
version: v1
mediaType: application/json
types:
ResponseNoId:
properties:
something1:
something2?:
ResponseId:
properties:
id:
something1:
something2?:
Response:
ResponseNoId|ResponseId
resourceTypes:
collection:
usage: Use this resourceType to represent a collection of items
description: A collection of <<resourcePathName|!uppercamelcase>>
get:
description: |
Get all <<resourcePathName|!uppercamelcase>>,
optionally filtered
is: [ hasResponseCollection: { typeName: <<typeName>> } ]
post:
description: |
Create a new <<resourcePathName|!uppercamelcase|!singularize>>
is: [ hasRequestItem: { typeName: <<typeName>> } ]
item:
usage: Use this resourceType to represent any single item
description: A single <<typeName>>
get:
description: Get a <<typeName>>
is: [ hasResponseItem: { typeName: <<typeName>> } ]
traits:
hasRequestItem:
body:
application/json:
type: <<typeName>>
hasResponseItem:
responses:
200:
body:
application/json:
type: <<typeName>>
hasResponseCollection:
responses:
200:
body:
application/json:
type: <<typeName>>[]
/myResource:
type: { collection: { typeName: Response } }
get:
/{id}:
type: { item: { typeName: Response } }
post:
body:
application/json:
You can mark the id field as readOnly to make the intent clear, although it won't have an effect on the way that the data is validated.
To affect validation, you can create a "Read" type and a "Write" type, where the "Read" type has the extra required id property.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"MyWriteEntity": {
"type": "object",
"properties": {
"something1": { "type": "string"},
"something2": { "type": "string"}
},
"required": "something1"
},
"MyReadEntity": {
"allOf": [
{ "$ref": "#/definitions/MyWriteEntity" },
{
"id": { "type": "string", "readOnly": true},
"required": ["id"]
}
]
}
}
}
The best way to do this is to create a RAML Library fragment, lets say "foo.raml" for a data model "foo" for resources /foos and /foos/{fooID}.
In the library, create three types:
fooInput:
properties:
something1:
something2:
fooOutput:
type: fooInput
properties:
id: integer
fooPatch:
properties:
something1?:
something2?:
Now in ONE file you have 3 data types. Use the Input version with PUT/POST, use the Output version for GET and use the Patch version for PATCH endpoints. This is even better when paired with resourceTypes.

Slate cannot show example value from swagger 2.0

I am creating API by Swagger 2.0. Everything is good on Swagger 2.0, but, when build it to Slate, all the example value is not shown, just show the data type.
Ex. In swagger, what I want is:
{
"cd": 0,
"data": {
"Num1": "113.90083333",
"Num2": "113.5991"
}
}
But in Slate interface after being built,
{
"cd": "string",
"data": {
"Num1": "number",
"Num2": "number"
}
}
YAML code:
/mar:
get:
tags:
- MP
operationId: "MP1"
produces:
- application/json
responses:
200:
description: "WELL"
schema:
type: object
properties:
cd:
type: string
example: 0
data:
type: object
properties:
Num1:
type: number
example: "113.90083333"
Num2:
type: number
example: "113.5991"

How to describe response object in swagger, using yaml?

We have following json response for /papers/15
{
"data": [
{
"id": 1,
"title": "foo"
},
{
"id": 2,
"title": "bar"
}
],
"meta": {
"total": 15
}
}
Does anyone know how to describe it swagger yaml file?
Ok, I just figured out how to do this, in case somebody will need id.
Beside dedicated model definitions section ("definitions") it is possible to do inline model descriptions. Code above will looks like:
responses:
"200":
description: Matched Objects
schema:
type: object
properties:
data:
type: object
properties:
authors:
type: array
items:
$ref: "#/definitions/object_with_id_and_title"