I tried to create minimal example of the problem.
Let's say we have simple return object:
public class Result {
#Schema(example = "2012-01-01")
private LocalDate sampleDate;
// omitted getter and setter
}
returned by simple JAX-RS endpoint:
#Path("/example")
#Produces(MediaType.APPLICATION_JSON)
public class Resource {
public List<Result> example() {
// omitted implementation
}
}
MicroProfile OpenAPI in Open Liberty will automatically generate following OpenAPI (Swagger) file:
openapi: 3.0.0
info:
title: Deployed APIs
version: 1.0.0
servers:
- url: http://localhost:9080/api
paths:
/example:
get:
operationId: example
responses:
default:
description: default response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Result'
components:
schemas:
Result:
type: object
properties:
sampleDate:
type: string
format: date
example: 2012-01-01
The problem is that embedded Swagger UI is displaying the date example as empty JS object:
I'm not sure if this is bug on Swagger UI side because if I don't provide any example in Java annotation = any example in OpenAPI file it will render the example as current day, e.g.:
[
{
"sampleDate": "2018-11-27"
}
]
Everything works correctly when I edit the OpenAPI output manually. Both single and double quotes fix the problem:
...
sampleDate:
type: string
format: date
example: '2012-01-01'
or
...
sampleDate:
type: string
format: date
example: "2012-01-01"
will produce expected output:
[
{
"sampleDate": "2012-01-01"
}
]
Question is how to change the annotations to get desired OpenAPI output.
Single quotes are automatically escaped:
#Schema(example = "'2012-01-01'")
private LocalDate sampleDate;
will produce:
...
sampleDate:
type: string
format: date
example: '''2012-01-01'''
Additional double quotes in Java doesn't have any effect on ouput:
#Schema(example = "\"2012-01-01\"")
private LocalDate sampleDate;
will produce same unquoted output:
...
sampleDate:
type: string
format: date
example: 2012-01-01
I know that I can write the OpenAPI yaml output manually but that is my last resort because I don't want to sacrifice automatic generation just because date examples are not behaving as I want. Maybe some OASFilter can be implemented to automatically wrap date's example values or I'm just missing something obvious here.
I've confirmed the behaviour that you're describing.
It the issue with Swagger-UI which is packaged with Microprofile OpenAPI, you could open issue here:
Swagger UI GitHub.
The value produced, without quotes is completely valid yaml, so UI
should be able to parse it as is.
Related
I have a project which is using spring-doc for it's generation of swagger so I am using OpenApi 3. The issue I am facing I believe is really coming from swagger-core which should have the functionality I need but I can't quite figure out how to get it to work the way I need.
I have a generic date class which is defined in hand written swagger like the below and reused in multiple places.
DateRange:
type: object
properties:
start:
type: string
description: Date fields are formatted according to the ISO 8601 specification.
format: date
example: '2022-01-01'
end:
type: string
description: Date fields are formatted according to the ISO 8601 specification.
format: date
example: '2022-01-01'
In my Java code it is something like the below. I tried adding the allOf since that is what I would normally use if I am writing the Swagger by hand, but I am unsure if I am actually using it correctly as I am not getting the behavior I want!
#Schema(description = "Some description.", allOf = {DateRange.class})
private DateRange someDateRange;
#Schema(description = "Some other description.", allOf = {DateRange.class})
private DateRange anotherDateRange;
This is how it's rendering which is not at all what I was expecting...
Does any one have any idea how I can fix this?
I have the following springboot request:
#Data
#ToString
public class OffsetDate {
public OffsetDateTime time;
}
And my request goes:
{
"time" : 20000101
}
Right now, that is being converted to date during serialization: 1970-01-01T05:33:20.101Z - which I don't want to happen.
I need to be able to specify the format and fail if it's invalid without custom annotations (request code is actually autogenerated from swagger yaml, hence I cannot modify the request).
Is there a way to do that?
I have an openApi spec which includes the following:
MyType:
type: string
enum:
- foo
- baz
which is used as:
"/v1/configuration/{configType}":
get:
operationId: GetConf
parameters:
- name: configType
in: path
required: true
schema:
$ref: "#/components/schemas/MyType"
Java generates the enum as:
public enum ConfigTypePathParamEnum {
FOO("foo"),
BAZ("baz")
Having written a test for the endpoint, i can only access the foo endpoint as "/v1/configuration/FOO" (which returns an http error code 400). What i want is "/v1/configuration/foo" to work.
This question is similar, but not quite the same:
Case Insensitive String parameter in schema of openApi
I am using openapi generator version 5.2.0.
I use spring-boot and that brings Jackson with it.
Jackson has some nice annotations that control serialisation/deserialisation, so all I have to do is add this method to my enum:
#JsonValue
public String toJson() {
return name().toLowerCase().replaceAll("_","-");
}
NB: since we use kebab-case rather than SNAKE_CASE, we also switch dashes for undescores.
I use OpenAPI spec to generate Java POJOs. What do I need to specify in Open API yaml to generate the equivalent of below POJO ?
...
#JsonIgnore
public String ignoredProperty;
...
I have the yaml spec as below
openapi: 3.0.0
info:
title: Cool API
description: A Cool API spec
version: 0.0.1
servers:
- url: http://api.cool.com/v1
description: Cool server for testing
paths:
/
...
components:
schemas:
MyPojo:
type: object
properties:
id:
type: integer
name:
type: string
# I want the below attribute to be ignored as a part of JSON
ignoreProperty:
type: string
the openapi generator supports vendor extensions. Specifically, for the Java generator, it supports the following extensions as of the time of writing. However, an up-to-date list can be found here.
Extension name
Description
Applicable for
Default value
x-discriminator-value
Used with model inheritance to specify value for discriminator that identifies current model
MODEL
x-implements
Ability to specify interfaces that model must implements
MODEL
empty array
x-setter-extra-annotation
Custom annotation that can be specified over java setter for specific field
FIELD
When field is array & uniqueItems, then this extension is used to add #JsonDeserialize(as = LinkedHashSet.class) over setter, otherwise no value
x-tags
Specify multiple swagger tags for operation
OPERATION
null
x-accepts
Specify custom value for 'Accept' header for operation
OPERATION
null
x-content-type
Specify custom value for 'Content-Type' header for operation
OPERATION
null
x-class-extra-annotation
List of custom annotations to be added to model
MODEL
null
x-field-extra-annotation
List of custom annotations to be added to property
FIELD
null
x-webclient-blocking
Specifies if method for specific operation should be blocking or non-blocking(ex: return Mono<T>/Flux<T> or return T/List<T>/Set<T> & execute .block() inside generated method)
OPERATION
false
You can use the x-field-extra-annotation vendor extension listed above to add annotations to any field. So, for your example, you can add the following:
openapi: 3.0.0
info:
title: Cool API
description: A Cool API spec
version: 0.0.1
servers:
- url: http://api.cool.com/v1
description: Cool server for testing
paths:
/
...
components:
schemas:
MyPojo:
type: object
properties:
id:
type: integer
name:
type: string
# I want the below attribute to be ignored as a part of JSON
ignoreProperty:
type: string
x-field-extra-annotation: "#com.fasterxml.jackson.annotation.JsonIgnore"
I faced the problem related to Swagger and Java. My lecturer sent me a Swagger file from which I should create a REST API. Also, that REST API should export the same Swagger documentation as Lecturers.
In the Swagger definitions I found that there should be created 2 Models: Odd(object) and Bet(array). Everything is fine with the Odd Model, but I do not find a solution on how to create Bet array. If I simply create an ArrayList named Bet in the getOdd method and put all Odd objects inside, the model will not be created.
I was looking for solutions, but I did not succeed. Thank you in advance.
Lecturer Swagger file:
swagger: "2.0"
info:
description: "Schema"
version: "1.0.0"
title: "API"
tags:
- name: "odds"
description: "Offer and return Odds"
schemes:
- "http"
paths:
/odds:
post:
tags:
- "odds"
summary: "Offer odds for a bet"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Odds that should be offered for a bet"
required: true
schema:
$ref: "#/definitions/Odds"
responses:
201:
description: "Odds have been created for bet"
400:
description: "Invalid format of Odds"
/odds/{betId}:
get:
tags:
- "odds"
summary: "Find Odds by Bet ID"
description: "Returns a list of odds for a given bet ID"
produces:
- "application/json"
parameters:
- name: "betId"
in: "path"
description: "ID of bet to return"
required: true
type: "integer"
format: "int64"
responses:
200:
description: "Odds are returned for bet ID"
schema:
$ref: "#/definitions/Bet"
400:
description: "Invalid Bet ID supplied"
404:
description: "Bet not found for given ID"
definitions:
Odds:
type: "object"
properties:
betId:
type: "integer"
format: "int64"
userId:
type: "string"
description: "ID of user who is offering the odds"
odds:
type: "string"
example: "1/10"
**Bet:
type: "array"
items:
$ref: '#/definitions/Odds'**
How Models should look like in Swagger
How getOdd method should look like in Swagger
I will paste some of my work done:
How my Models looks like in Swagger
How my getOdd method looks like in Swagger
My Rest Controller:
#RestController
#RequestMapping("/api")
public class OddController {
#Autowired
OddRepository oddRepository;
#GetMapping("/odds/{betId}")
public Optional<Odd> getOdd(#PathVariable Long betId) {
Optional<Odd> theOdd=oddRepository.findById(betId);
return theOdd;
}
#PostMapping("/odds")
public Odd addOdd(#RequestBody Odd odd) {
odd.setBetId((long) 0);
oddRepository.save(odd);
return odd;
}
My Odd class:
#Entity
#Table(name="odds")
#Data
public class Odd {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="betid")
private Long betId;
#Column(name="userid")
private String userId;
#Column(name="odds")
private String odds;
}
You can use annotations to control the generation of the swagger definitions. There is a old and a new api to do that:
Old:
https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X
New:
https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Annotations
In the lecture swagger file 'swagger: "2.0"' is used. Therefore it would be the old one. The new one is producing swagger files for OpenApi 3.0.
Specially the annotation #ApiOperation and #ApiModelOperation could be interesting for you to solve your problem.
See also the JavaDoc:
#ApiOperation: https://docs.swagger.io/swagger-core/v1.5.X/apidocs/index.html?io/swagger/annotations/ApiOperation.html
#ApiModelProperty: https://docs.swagger.io/swagger-core/v1.5.X/apidocs/index.html?io/swagger/annotations/ApiModelProperty.html