How to create Crystal language Hash where values can be any type? - openapi

I'm working on representing an API where a response contains a hash where the keys are of type String and the values can be of any type. Is there a way to represent this in Crystal?
I did not see a way to represent this looking through Crystal docs on types:
https://crystal-lang.org/reference/1.6/syntax_and_semantics/literals/index.html
https://crystal-lang.org/reference/1.6/syntax_and_semantics/literals/hash.html
In OpenAPI Spec, this is described as a free-form object:
https://swagger.io/docs/specification/data-models/dictionaries/#free-form
Free-Form Objects
If the dictionary values can be of any type (aka free-form object), use additionalProperties: true:
type: object
additionalProperties: true
This is equivalent to:
type: object
additionalProperties: {}
In Go, this would be represented as map[string]any or map[string]interface{}.

Given that everything is an object in Crystal, the following compiles for me:
Hash(String, Object)
Everything is an object
In Crystal everything is an object. The definition of an object boils down to these points:
It has a type
It can respond to some methods
This is everything you can know about an object: its type and whether it responds to some method.
An object's internal state, if any, can only be queried by invoking methods.
Ref: https://crystal-lang.org/reference/1.6/syntax_and_semantics/everything_is_an_object.html

Related

Golang Swagger annotation for enum input parameter

I am not sure how to specify annotation for an input string parameter for a rest call. Where input parameter can take one of three possible string values.
If I have to assume there will be a drop down menu with these three value (containers/bundles/web) and the user will chose one of them. Previously I am referring to this documentation to create annotation for an in parameters.
I am trying to annotate go code, so that I can generate swagger.yaml automatically (swagger generate spec -o ./swagger.yaml --scan-models). Unfortunately, I couldn't find an annotated example that expects enums or the input parameters is limited to certain values. Looks for some code examples.
some thing like this with enum annotation should work.
// swagger:parameters artifactInfo
type ArtifactTypeParam struct {
// The type of artifact
// in: path
// enum: container,bundle,executbale
// required: true
ArtifactType string `json:"artifactType"`
}

In OpenAPI, can I use a regular schema component as a parameter?

I have an endpoint defined in my API that takes a path parameter.
The valid values for that parameter are already expressed as an enum, which I've defined as a schema component and used in a response.
Two questions:
If you can just use a reference to that schema component as the parameter, why ever set up dedicated parameter components instead of using a generic schema component that you can re-use anywhere?
If you should use parameters instead of generic schemas, can you create a parameter component that refers to a schema component? I can't find any syntax to do this that passes validation.
I'd paste my definitions here but I can't find any formatting option that doesn't make a hideous mess.
If you can just use a reference to that schema component as the parameter, why ever set up dedicated parameter components instead of using a generic schema component that you can re-use anywhere?
Parameter definitions have additional attributes not present in schemas, such as the parameter location in the request (in: path, in: query, etc.), serialization method for array and object values, and others. A schema is just one of the parameter attributes, but a schema alone does not provide enough information to effectively describe a parameter.
can you create a parameter component that refers to a schema component?
Yes. Parameters have a schema, it can be an inline schema or a $ref:
paths:
/something/{role}:
get:
parameters:
- $ref: '#/components/parameters/role'
...
components:
parameters:
role:
in: path
name: role
required: true
schema:
$ref: '#/components/schemas/UserRole' # <-----
schemas:
UserRole:
type: string
enum: [user, admin]

Define array in Swagger OpenAPI annotation

I`m using Swagger Editor with OpenAPI 3.0, and I installed swagger-php library. Now I have a php function with one of its parameter as array, such as:
array[(1,2),(2,3),(6,9)]
How do I write up the annotation of this array in order to call this function.
There are different solutions. I would suggest to implement it with with arrays of objects as it stands in documentation.
arrayOfObjects
description: 'basic array of objects in OpenAPI'
type: array
items:
type: object
properties:
num:
type: integer
More info please find here:
Data Types - Arrays

Swagger Definition of primitive types

Is it possible to define a swagger definition/model for a primitive type? For instance, consider the following
definitions:
program_name:
type: string
description: Unique string id
However, the above example comes back with many errors (swagger expects a properties field for example) and no examples employ any definition that is not of type: object.
The intention is to use this as a subcomponent to another model as well as a parameter -- to reuse the already defined component in some way.
Think of this as a swagger typedef
EDIT: According to the spec, a definition object is the same as a schema object http://swagger.io/specification/#schemaObject, which states that it can accept primitive types.
Also, assuming that primitive types can exist in the definitions section, could simple parameter types (query, path etc.) reference primitive definition types?
A primitive schema as in your example is valid and can be used in whenever a Schema object is expected, for example, as a subcomponent of another schema:
definitions:
Program:
type: object
properties:
program_name:
$ref: "#/definitions/program_name"
# This becomes:
# type: object
# properties:
# program_name:
# type: string
# description: Unique string id
or as an operation body parameter or response schema:
paths:
/something:
post:
summary: POSTs and returns a string
parameters:
- in: body
name: program_name
schema:
$ref: "#/definitions/program_name"
responses:
"200":
description: OK
schema:
$ref: "#/definitions/program_name"
However, simple parameters - path, query, header and form - do not use the schema keyword (they use type instead) and so they cannot reference schemas from definitions.
This will be changed in the next version, OpenAPI 3.0, where schema will be used for all parameter types.

Alternate fields in HTTP POST request body

I've been looking for the best way to specify a body type for an HTTP POST request that has two fields that are mutually exclusive.
I'm using swagger for the API specification, and I have one request that must have either field_A or field_B, but not both.
Right now I am setting both fields as optional, describing the behaviour in the spec (when to set one field or the other), and validating the input on the server. If none of the fields is filled I am returning a 400-Bad-request.
My question is whether or not this is the correct approach (would it be more RESTful if I specify an extra content-type?), or if there is something in Swagger that allows me to make this behaviour more obvious.
I came across an API that solved my issue.
For a given field, the type for that field is extensible (like a base class, and multiple extending classes). To distinguish between the different sub-types there is a discriminator field.
For example (YAML in swagger format), type Foo is extensible and has subtypes FooA and FooB. The discriminator is a type field:
definitions:
Foo:
type: object
properties:
type: string
x-extensible-enum:
- FOO_A
- FOO_B
discriminator: type
required:
- type
FOO_A:
allOf:
- $ref: '#/definitions/Foo'
- type: object
properties:
field_a:
type: string
required:
- field_a
FOO_B:
allOf:
- $ref: '#/definitions/Foo'
- type: object
properties:
field_b:
type: integer
format: int32
required:
- field_b
This makes deserialisation more complex, but it's a quite interesting approach and very flexible.