Considering I need to refer to a json with the following format:
{
"data": {
"type": "ObjectA"
}
}
When I write JSON schema (or more specifically, schema object of OpenAPI Specification v3.0.3) for this json request, I write
components:
schemas:
Data:
type: object
required:
- data
properties:
data:
$ref: '#components/schemas/ObjectA'
ObjectA:
type: object
properties:
type:
type: string
ObjectB:
type: object
properties:
type:
type: string
some_properties:
type: string
... and I refer to it using $ref: '#components/schemas/Data'.
However now there is the other json to deal with, which is very similar to the one above except that the object in data property is not of type ObjectA, it is ObjectB instead.
{
"data": {
"type": "ObjectB",
"some_properties": "which is different from ObjectA"
}
}
Is there a way for me to reuse the schemas for Data above without creating a new schema (so it is like injecting #components/schemas/ObjectA or #components/schemas/ObjectB into Data whenever needed)?
I have considered using oneOf but it does not fit since only a specific object is valid for a specific API endpoint (even though all are under the data property) instead of any one of the available objects.
In your simple example, it seems unnecessary to re-use the simple Data definition. However, assuming your actual structure is more complex you could combine the general attributes with the specific ones via allOf, e.g.
components:
schemas:
BaseData:
type: object
required:
- data
properties:
data:
type: object
properties:
type:
type: string
required:
- type
DataA:
allOf:
- $ref: '#components/schemas/BaseData'
- type: object
properties:
data:
$ref: '#components/schemas/ObjectA'
DataB:
allOf:
- $ref: '#components/schemas/BaseData'
- type: object
properties:
data:
$ref: '#components/schemas/ObjectB'
ObjectA:
type: object
properties:
type:
const: ObjectA
ObjectB:
type: object
properties:
type:
const: ObjectB
some_properties:
type: string
required:
- some_properties
Depending on the actual complexity, the schema might be easier to read/maintain if the shared parts are simply duplicated.
Related
my question maybe seems to be easy, but I can't implement this on my YAML files. I would like to generate the API responses from YAML files, but I've a problem. In my JSON files, there's a key named 'type', like this:
"type": {
"id": 5,
"name": "TRONTON",
}
This key never been returned from the YAML file, because I think it's have a colliding with type parameters on YAML format itself for describing datatypes. The full code of YAML file is this:
components:
schemas:
myapi:
type: object
properties:
type:
type: object
properties:
id:
type: number
name:
type: string
Any one can help me? Thanks
I'm trying to setup an open api spec for the following snippet of JSON:
"test1": {
"1739573957": {
"tester1": 123,
"tester2": "Company"
},
"64903826718": {
"tester1": 123,
"tester2": "Company"
}
"5902849189": {
"tester1": 123,
"tester2": "Company"
}
}
The objects inside test1 have randomized guids and are listed in a way that typically would be an array, but is not. There could potentially be an infinite number of objects inside test 1. Anyone know how to set this up?
test1 is a string-to-object dictionary and can be defined as follows (assuming OpenAPI 3):
components:
schemas:
Tester: # Or however you would name the nested objects
tester1:
type: integer
example: 123
tester2:
type: string
example: Company
...
test1:
type: object
additionalProperties:
$ref: '#/components/schemas/Tester'
# Optional example for the `test1` property
example:
'1739573957':
tester1: 123
tester2: Company
'64903826718':
tester1: 123
tester2: Company
The objects inside test1 have randomized guids
In OpenAPI 3.1, you can use patternProperties instead of additionalProperties to define that the keys inside test1 are numeric strings. Earlier OpenAPI versions don't have a way to define the format of dictionary keys.
# openapi: 3.1.0
test1:
type: object
patternProperties: # <-----
'^\d+$': # <-----
$ref: '#/components/schemas/Tester'
You are looking for the free-form-object:
A free-form object (arbitrary property/value pairs) is defined as:
type: object
This is equivalent to
type: object
additionalProperties: true
and
type: object
additionalProperties: {}
However, if you can change the API, I'd highly recommend to change it to an array of tests or whatever the object defines. Put the id as property into this object and you're good to go. This makes creating DTOs for it a lot easier.
This is the Schema definition.
serviceArea: [{
states: [{
type: String
}],
districts: [{
type: String
}],
cities: [{
type: String
}]
}]
This is the swagger definition.
serviceArea:
- states:
- type: String
districts:
- type: String
cities:
- type: String
I am getting the above mentioned error. Please help. Thanks in advance.
Here is the swagger editor in the browser.
Assuming serviceArea is supposed to be an object with properties states, districts and cities, the definition should look like this:
serviceArea:
type: object
properties:
states:
type: string
districts:
type: string
cities:
type: string
UPDATE with regard to OP's comments:
It's an array of arrays.
An array of arrays is described as:
serviceArea:
type: array
items:
type: array
items:
type: string
Another error is here:
type:
- number
- "null"
type must be a single type such as type: number, not an array of types. Also, the OpenAPI Specification 2.0 does not support the null type. Some tools use the extension property x-nullable: true to indicate nullable types, so you can try this:
type: number
x-nullable: true
nullable will be supported natively in the next version, OpenAPI 3.0.
I'd like to post a JSON object within the body of a REST API call. The attribute dataof this DATA object contains a mandatory timestampattribute and then a series of various attributes depending on the source of the Data object. As far as I understood additionalPropertiesis meant for this and defaults to falseor specifies the schema object for every non-defined attribute.
Following Swagger YAML
/my/path:
post:
tags: [Tag]
description: Description
parameters:
- name: data
in: body
description: The actual data.
required: false
type: object
schema:
$ref: "#/definitions/Data"
definitions/
Data:
type: object
properties:
source:
type: string
data:
type: object
properties:
timestamp:
type: string
format: date-time
additionalProperties:
type: string
should pass both objects send:
{
"source": "A",
"data": {
"timestamp": "2016-10-26T01:12:40.329Z",
}
}
and:
{
"source": "B",
"data": {
"timestamp": "2016-10-26T01:12:40.329Z",
"newProp":"newValue"
}
}
However all I receive is a validation Error:
ValidationError: child "data" fails because ["test" is not allowed]
Is there anything I'm doing wrong or am I misinterpreting the attribute described at the docs:
http://swagger.io/specification/
I'm not sure if your solution got your past the problem. I see a few differences from your original problem schema:
timestamp now uses date instead of datetime format.
timestamp is now required.
additionalProperties is set to true.
However, there's a set of obscure limitations in Swagger with respect to additionalProperties, which we've documented in detail here.
Essentially, while your original schema is perfectly valid according to the Swagger specification, the swagger-core Java library won't process it correctly. It will discard either your explicitly defined timestamp property, or will discard additionalProperties.
The fix, surprisingly, is to extract the embedded schema for the data property to its own top-level schema definition:
definitions:
Data:
type: object
properties:
source:
type: string
data:
$ref: "#/definitions/DataValues"
DataValues:
type: object
properties:
timestamp:
type: string
format: date-time
additionalProperties:
type: string
I think your revised schema won't work correctly, because additionalProperties boolean values of true or false are ignored by swagger-core. Apparently this was an oversight in the specification; Swagger didn't intend to support this aspect of JSON Schema.
I actually figured it out myself, for reference:
definitions/
Data:
type: object
properties:
source:
type: string
data:
required:
- timestamp
type: object
properties:
timestamp:
type: string
format: date
additionalProperties: true
I am implementing an API-first application with the help of Swagger. One of the most important objects to be returned is a DICOM object, which returns a collection of attributes with flexible names, for example:
{
"00080005": {"vr":"CS","Value":["ISO_IR 100"]},
"00080020": {"vr":"DA","Value":["20160602"]},
"00080030": {"vr":"TM","Value":["171855.7490"]},
"00080050": {"vr":"SH","Value":["1234"]},
"00080090": {"vr":"PN","Value":[{"Alphabetic":"Parikh MD^Anush^M"}]}
}
So I cannot know the name of all the attributes in advance (00080005, 00080030, etc.) although the file structure is very uniform.
My concrete question is: what would be the schema definition for such JSON document.
I have tried the following without success:
definitions:
DicomMetadataJson:
type: object
patternProperties:
^\d{8}:
type: object
but the Swagger Editor returns an error like:
code: "OBJECT_ADDITIONAL_PROPERTIES"
message: "Additional properties not allowed: patternProperties"
description: "A deterministic version of a JSON Schema object."
OpenAPI (fka. Swagger) use only a subset of JSON Schema v4 which, unfortunately, do not propose patternProperties.
But given the provided example is a map, you can describe it using additionalProperties:
swagger: "2.0"
info:
version: 1.0.0
title: Hashmap
paths: {}
definitions:
DicomMetadataJson:
additionalProperties:
properties:
vr:
type: string
Value:
type: array
items:
type: string
The key is not defined and is supposed to be a string (therefore you cannot enforce it's format).
Note that SwaggerUI Swagger UI do not render them for now.The issue is tracked here https://github.com/swagger-api/swagger-ui/issues/1248
In the meanwhile you can use this trick define a non required property (default in the example below) of the same type of the map's objects and give some hint within the description:
swagger: "2.0"
info:
version: 1.0.0
title: Hashmap
paths: {}
definitions:
MetaData:
properties:
vr:
type: string
Value:
type: array
items:
type: string
DicomMetadataJson:
description: 'A <string,MetaData> map, default key is only for documentation purpose'
properties:
default:
$ref: '#/definitions/MetaData'
additionalProperties:
$ref: '#/definitions/MetaData'
Concerning the quote The schema exposes two types of fields. Fixed fields, which have a declared name, and Patterned fields, which declare a regex pattern for the field name. Patterned fields can have multiple occurrences as long as each has a unique name., it concerns the format of the OpenAPI specification itself and not the objects used by the API described with an OpenAPI specification.