I have a Get endpoint with an object & array of object type query parameters, as shown below
[DataContract]
[Api(Description = "Get endpoint with object query param")]
public class GetEndpointWithObjectQueryParam : IReturn<PagedResponse<string>>
{
[ApiMember(Description = "The account ID")]
[DataMember]
public Guid? AccountId { get; set; }
[ApiMember(Description = "The paging options object which the caller can pass in to override the default paging options")]
[DataMember]
public PagingOptions PagingOptions { get; set; }
[ApiMember(Description = "Limits the records based on specified filter conditions")]
[DataMember]
public List<SearchFilter> Filters
{
get => this.PagingOptions?.Filters;
set
{
this.PagingOptions = this.PagingOptions ?? new PagingOptions();
this.PagingOptions.Filters = value;
}
}
}
This generates following open api spec
{
"x-explorer-enabled": false,
"swagger": "2.0",
"info": {
"title": "Test Platform",
"version": "1.0"
},
"host": "localhost:44301",
"basePath": "/",
"schemes": [
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/GetEndpointWithObjectQueryParam": {
"get": {
"tags": [
"GetEndpointWithObjectQueryParam"
],
"summary": "Get endpoint with object query param",
"description": "Get endpoint with object query param",
"operationId": "GetEndpointWithObjectQueryParam_Get",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "AccountId",
"in": "query",
"description": "The account ID",
"type": "string",
"required": false
},
{
"name": "PagingOptions",
"in": "query",
"schema": {
"$ref": "#/definitions/PagingOptions"
},
"description": "The paging options object which the caller can pass in to override the default paging options",
"required": false
},
{
"name": "Filters",
"in": "query",
"description": "Limits the records based on specified filter conditions",
"type": "array",
"items": {
"$ref": "#/definitions/SearchFilter"
},
"collectionFormat": "multi",
"required": false
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"$ref": "#/definitions/PagedResponse_String_"
}
}
},
"deprecated": false
},
"parameters": [
{
"$ref": "#/parameters/Accept"
}
]
}
},
"definitions": {
"Object": {
"properties": {},
"description": "Object",
"type": "object"
},
"GetEndpointWithObjectQueryParam": {
"title": "GetEndpointWithObjectQueryParam",
"properties": {
"Filters": {
"description": "Limits the records based on specified filter conditions",
"type": "array",
"items": {
"$ref": "#/definitions/SearchFilter"
}
},
"PagingOptions": {
"$ref": "#/definitions/PagingOptions",
"description": "The paging options object which the caller can pass in to override the default paging options"
}
},
"description": "Get endpoint with object query param",
"type": "object"
},
"SearchFilter": {
"title": "SearchFilter",
"properties": {
"Operation": {
"type": "string"
},
"PropertyName": {
"type": "string"
},
"PropertyType": {
"type": "string"
},
"PropertyValue": {
"$ref": "#/definitions/Object"
}
},
"description": "SearchFilter",
"type": "object"
},
"PagingOptions": {
"title": "PagingOptions",
"properties": {
"Filters": {
"type": "array",
"items": {
"$ref": "#/definitions/SearchFilter"
}
},
"PageNumber": {
"type": "integer",
"format": "int32"
},
"PageSize": {
"type": "integer",
"format": "int32"
},
"SortBy": {
"type": "string"
},
"SortByDirection": {
"type": "string"
},
"ThenBy": {
"type": "string"
},
"ThenByDirection": {
"type": "string"
}
},
"description": "PagingOptions",
"type": "object"
},
"PagedResponse_String_": {
"title": "PagedResponse`1",
"properties": {
"CorrelationId": {
"type": "string"
},
"RequestId": {
"type": "integer",
"format": "int64",
"x-nullable": false
},
"ResponseStatus": {
"$ref": "#/definitions/ResponseStatus"
},
"Status": {
"type": "integer",
"format": "int32",
"x-nullable": false
},
"Warnings": {
"type": "array",
"items": {
"$ref": "#/definitions/ResponseError"
}
},
"CurrentPage": {
"type": "integer",
"format": "int32",
"x-nullable": false
},
"PageSize": {
"type": "integer",
"format": "int32",
"x-nullable": false
},
"TotalPages": {
"type": "integer",
"format": "int32",
"x-nullable": false
},
"TotalRecords": {
"type": "integer",
"format": "int64",
"x-nullable": false
},
"Records": {
"type": "array",
"items": {
"type": "string"
}
}
},
"description": "PagedResponse<String>",
"type": "object"
},
"ResponseStatus": {
"title": "ResponseStatus",
"properties": {
"ErrorCode": {
"type": "string"
},
"Message": {
"type": "string"
},
"StackTrace": {
"type": "string"
},
"Errors": {
"type": "array",
"items": {
"$ref": "#/definitions/ResponseError"
}
},
"Meta": {
"$ref": "#/definitions/Dictionary_String_String_"
}
},
"description": "ResponseStatus",
"type": "object"
},
"ResponseError": {
"title": "ResponseError",
"properties": {
"ErrorCode": {
"type": "string"
},
"FieldName": {
"type": "string"
},
"Message": {
"type": "string"
},
"Meta": {
"$ref": "#/definitions/Dictionary_String_String_"
}
},
"description": "ResponseError",
"type": "object"
},
"Dictionary_String_String_": {
"title": "Dictionary<String,String>",
"additionalProperties": {
"type": "string"
},
"description": "Dictionary<String,String>",
"type": "object"
}
},
"parameters": {
"Accept": {
"name": "Accept",
"in": "header",
"description": "Accept Header",
"type": "string",
"required": true,
"enum": [
"application/json"
]
}
},
"securityDefinitions": {
"Bearer": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
}
},
"tags": [
{
"name": "GetEndpointWithObjectQueryParam"
}
]
}
We are trying to import this to readme.io to generate documentation but are facing following errors from the swagger validator at readme.io
error: "Swagger schema validation failed.
Data does not match any schemas from 'oneOf' at #/paths//GetEndpointWithObjectQueryParam/get/parameters/2
Data does not match any schemas from 'oneOf' at #/paths//GetEndpointWithObjectQueryParam/get/parameters/2
Missing required property: schema at #/
Data does not match any schemas from 'oneOf' at #/
No enum match for: multi at #/collectionFormat
Additional properties not allowed: title at #/items
Additional properties not allowed: title at #/items
No enum match for: false at #/required
Missing required property: $ref at #/paths//GetEndpointWithObjectQueryParam/get/parameters/2
Data does not match any schemas from 'oneOf' at #/paths//GetEndpointWithObjectQueryParam/get/parameters/1
Data does not match any schemas from 'oneOf' at #/paths//GetEndpointWithObjectQueryParam/get/parameters/1
No enum match for: query at #/in
Missing required property: type at #/
Missing required property: $ref at #/paths//GetEndpointWithObjectQueryParam/get/parameters/1
JSON_OBJECT_VALIDATION_FAILED"
This is primarily pointing towards parameters 1 & 2 which are PagingOptions & Filters which are complex query parameters, digging deeper i found that this could be because ServiceStack generates Open API 2.0 based spec which only supports primitive query parameters & hence the above parameter definition might be wrong ?
and therefore at the other end of the problem, readme.io which accepts swagger 2.0 but converts it to 3.0 sees the above spec as invalid 2.0 spec.
So my query is, for the above use case of complex typed query parameters is there a workaround that would allow SS to emit the spec which can resolve the above issue ?