Videos
Sharing my working approach for the issue, I have done a workaround for the @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(schema = @Schema(implementation = Map.class) the Schema is coming as String issue.
I have declared a custom schema called Map in the OpenAPI bean declaration as below
new OpenAPI()
.components(new Components()
.addSchemas("Map", new Schema<Map<String, Object>>().addProperties("< * >", new ObjectSchema())
))
.....
.....
and used the above schema in the Schema declaration as below
@io.swagger.v3.oas.annotations.parameters.RequestBody(
content = @Content(mediaType = APPLICATION_JSON_VALUE,
schema = @Schema(ref = "#/components/schemas/Map"))
The above approach can be used in the place of ApiResponse also as below
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200",
content = @Content(mediaType = APPLICATION_JSON_VALUE,
schema = @Schema(ref = "#/components/schemas/Map"))
Note: If we use the above custom schema approach, we don't need to alter or ignore any of the types which SpringDoc is using internally.
I have one API endpoint, the request body expects a HashMap. There is not much information on how to fix the "Example value" issue. Prasanth's answer lead me to the right place. I'm posting my solution for completeness but all credit goes to him. (PS: I tried to upvote his answer but I don't have enough "points")
The configurations side:
@Configuration
@OpenAPIDefinition
public class DocsConfiguration {
@Bean
public OpenAPI customOpenAPI() {
Schema newUserSchema = new Schema<Map<String, Object>>()
.addProperties("name",new StringSchema().example("John123"))
.addProperties("password",new StringSchema().example("P4SSW0RD"))
.addProperties("image",new StringSchema().example("https://robohash.org/John123.png"));
return new OpenAPI()
//.servers(servers)
.info(new Info()
.title("Your app title")
.description("App description")
.version("1.0")
.license(new License().name("GNU/GPL").url("https://www.gnu.org/licenses/gpl-3.0.html"))
)
.components(new Components()
.addSchemas("NewUserBody" , newUserSchema)
);
}
}
The controller side:
@io.swagger.v3.oas.annotations.parameters.RequestBody(
content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(ref = "#/components/schemas/NewUserBody")))
@PostMapping("/v1/users")
public Response<User> upsertUser(@RequestBody HashMap<String,Object> user) {
//Your code here
}
After longer fight with using Swagger for specifying REST API and reusing it in related test suites, I will share my own experience with it (answering my own question).
Swagger supports only subset of JSON Schema Draft 4
Specification of Swagger 1.2 and 2.0 states, it supports only subset of JSON Schema Draft 4 (s. here). This means, that:
- one cannot rely, that each valid JSON Schema can be completely supported by Swagger.
- thinking of XML, Swagger supports only canonical representation of subset of JSON structures provided by JSON Schema Draft 4.
In other words:
- Swagger (1.2 and 2.0) does not support usage of many JSON structures, which are valid in terms of JSON Schema Draft 4 (the same applies to Draft 3).
- Swagger does not support general XML data structures, only very restricted structures are allowed.
In practice, you cannot start with designing your data in JSON or XML, with Swagger you have to start and end with Swagger.
Getting JSON Schema is theoretically possible, but not easy
I have spent some time coding a library, which would take Swagger API Specification and create JSON Schema Draft 4. I gave up for couple of reasons:
- it was not easy at all
- got disappointed finding, that I can use only subset of what JSON Schema provides. We had some JSON payload already proposed and had to start modifying it just to fit what Swagger specification framework allows.
Apart from having really nice looking UI for showing and testing the API (yes, everybody agrees, it is visually very pleasing), I have found it weird, that a specification framework is not allowing us to use what we want, but adds unexpected restrictions to our design.
If you want full JSON or XML Schema support, use RAML
Researching other API specification frameworks, I have found RAML. As it is built from ground up by supporting any JSON Schema Draft 3/4 or W3C XML Schema 1.0 data structures, the experience was excellent - having structure of my payload designed, I was able authoring API specification very quickly and following validation of real requests and responses against defined schemas was very easy, as the schemas are essentials components of the specification without adding any restrictions on them.
RAML was at version 0.8 that time (version 1.0 was not released yet).
Correcting the question leads to real solution
Good question makes half of the solution. My question was wrong as it missed fulfilling my real expectations. Corrected question would be:
What specification framework and technique to use, to specify REST API using payload defined by arbitrary JSON Schema Draft 4 or W3C XML Schema 1.0.
My answer to such a question would be:
- Design your payload in JSON Schema Draft 4 or W3C XML Schema
- Describe your REST API by means of RAML (v0.8 at the moment).
There might be other specification frameworks usable, but Swagger (neither v1.2 nor v2.0) is definitely not the case. Apart from providing really a lot of features (code generation, very nice looking documentation of the API and much more), it simply fails in providing solution to the updated question stated above.
There is a python tool to do the same by the name openapi2jsonschema.
You can simply install it using pip.
The readme for openapi2 shows the simplest way to use it:
openapi2jsonschema https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json
Hope this helps.
OpenAPI 3.0
Multiple examples are only supported at the media type level and are not supported inside schemas. Schemas and properties can only have a single example, e.g.
partitionProperty:
type: string
example: '2016-03-04T03:00:00'
In other words, this won't work:
MainObject:
type: object
properties:
..
examples: # <--- Won't work
minimal:
summary: Minimal example
value:
foo: bar
full:
summary: Example with all properties
value:
foo: bar
baz: xyzzy
If you want multiple examples, you need to use request examples or response examples instead:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MainObject'
examples:
minimal:
summary: Minimal example
value:
foo: bar
full:
summary: Example with all properties
value:
foo: bar
baz: xyzzy
OpenAPI 3.1
OAS 3.1 uses a newer version of JSON Schema which supports multiple examples in schemas and properties. Unlike media type examples which is a map of named Example Objects, schema-level and property-level examples is a plain list of example values.
MyObject:
type: object
properties:
prop1:
type: string
# Property-level examples
examples:
- foo
- bar
prop2:
type: integer
# Object-level examples
examples:
- prop1: hello
prop2: 5
- prop1: world
prop2: 0
If you are stuck on OpenAPI v3.0.x and need (strongly desire) multiple examples, here is a hackish way to provide them within the schemas section (Note single quotes inside and double quotes outside):
common_phone:
type: string
maxLength: 14
minLength: 1
example: "'(614) 555-1212' or '614.555.1212' or '614-555-1212' or '6145551212'"