Skip to content

Commit 4993eca

Browse files
author
gcornacchia
committed
Merge branch 'release/1.0.2'
2 parents b78a66b + 04ff9ef commit 4993eca

10 files changed

Lines changed: 2828 additions & 118 deletions

File tree

.github/workflows/maven.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,8 @@ jobs:
2424
cache: maven
2525
- name: Build with Maven
2626
run: mvn -B package --file pom.xml
27+
- name: Publish Unit Test Results
28+
uses: EnricoMi/publish-unit-test-result-action@v1
29+
if: always()
30+
with:
31+
files: "target/surefire-reports/*.xml"

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
4+
1.0.2 - 18/07/2022
5+
- support for oas 3.0.X conversion to json schema draft4
6+
37
1.0.1 - 28/04/2022
48

59
- removed unused definition in json schema file for each request/response

README.md

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,71 @@
11
# OpenAPI2JsonSchema4J
22

3-
Maven plugin that converts swagger 2.0 models into self contained json schema files for every request or response.
3+
Maven plugin that converts swagger 2.0/OAS 3.0.x schema objects into self contained json schema DRAFT_4 files for every request or response.
44

55
[![Java CI with Maven](https://github.com/imolainformatica/OpenAPI2JsonSchema4J/actions/workflows/maven.yml/badge.svg?branch=develop)](https://github.com/imolainformatica/OpenAPI2JsonSchema4J/actions/workflows/maven.yml)
6+
7+
8+
9+
10+
11+
### Interface requirements
12+
13+
14+
15+
- Each operation MUST have a non-empty OperationID field
16+
- Each operation MUST not declare inline request/response body but always reference to Object Schema (no error is thrown, only a warn log)
17+
18+
19+
20+
21+
### Notes about OAS 3.0.X conversion to DRAFT_4 Json Schema
22+
23+
* OAS `nullable` field adds `"null"` to `type` array if `nullable` is `true`
24+
* OAS specific properties are deleted from JsonSchema output (discriminator, deprecated, xml, example,...)
25+
* format attributes are maintened as-is
26+
27+
28+
29+
30+
31+
### Usage
32+
33+
**Maven goal**: generate
34+
35+
**Default lifecycle phase**: generate-sources
36+
37+
#### Configuration
38+
39+
| Parameter | Description | Required |
40+
| --------------- | ------------------------------------------------------------ | -------- |
41+
| strict | true / false, if "true" adds an additionalProperties = false field in complex object to avoid other json fields to appear | Y |
42+
| outputDirectory | json schema files are written here | Y |
43+
| interfaceFile | path to swagger/oas file (in yaml or json format) | Y |
44+
45+
46+
47+
#### Example
48+
49+
```xml
50+
<plugin>
51+
<groupId>it.imolinfo.maven.plugins</groupId>
52+
<artifactId>openapi2jsonschema4j</artifactId>
53+
<version>1.0.1</version>
54+
<configuration>
55+
<strict>true</strict>
56+
</configuration>
57+
<executions>
58+
<execution>
59+
<id>exec-id</id>
60+
<phase>generate-sources</phase>
61+
<configuration>
62+
<outputDirectory>${basedir}/target/json-schema</outputDirectory>
63+
<interfaceFile>${basedir}/path/to/swagger.json</interfaceFile>
64+
</configuration>
65+
<goals>
66+
<goal>generate</goal>
67+
</goals>
68+
</execution>
69+
</executions>
70+
</plugin>
71+
```

pom.xml

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>it.imolinfo.maven.plugins</groupId>
55
<artifactId>openapi2jsonschema4j</artifactId>
6-
<version>1.0.1</version>
6+
<version>1.0.2</version>
77
<packaging>maven-plugin</packaging>
88

99
<name>OpenAPI2JsonSchema4J</name>
@@ -325,7 +325,7 @@
325325
<dependency>
326326
<groupId>com.google.code.gson</groupId>
327327
<artifactId>gson</artifactId>
328-
<version>2.8.2</version>
328+
<version>2.8.9</version>
329329
</dependency>
330330
<dependency>
331331
<groupId>com.squareup.okhttp</groupId>
@@ -357,14 +357,22 @@
357357
<dependency>
358358
<groupId>com.fasterxml.jackson.core</groupId>
359359
<artifactId>jackson-core</artifactId>
360-
<version>2.10.3</version>
360+
<version>2.12.2</version>
361361
</dependency>
362362
<dependency>
363363
<groupId>com.fasterxml.jackson.core</groupId>
364364
<artifactId>jackson-databind</artifactId>
365-
<version>2.10.5.1</version>
365+
<version>2.12.6.1</version>
366366
</dependency>
367367

368+
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310 -->
369+
<dependency>
370+
<groupId>com.fasterxml.jackson.datatype</groupId>
371+
<artifactId>jackson-datatype-jsr310</artifactId>
372+
<version>2.12.2</version>
373+
</dependency>
374+
375+
368376
<dependency>
369377
<groupId>commons-lang</groupId>
370378
<artifactId>commons-lang</artifactId>
@@ -378,10 +386,11 @@
378386
<version>1.2.12</version>
379387
</dependency>
380388

389+
381390
<dependency>
382-
<groupId>io.swagger</groupId>
391+
<groupId>io.swagger.parser.v3</groupId>
383392
<artifactId>swagger-parser</artifactId>
384-
<version>1.0.54</version>
393+
<version>2.1.1</version>
385394
</dependency>
386395

387396
<dependency>
@@ -399,7 +408,7 @@
399408
<dependency>
400409
<groupId>io.swagger</groupId>
401410
<artifactId>swagger-inflector</artifactId>
402-
<version>1.0.19</version>
411+
<version>2.0.7</version>
403412
<scope>test</scope>
404413
</dependency>
405414

src/main/java/it/imolainformatica/openapi2jsonschema4j/base/BaseJsonSchemaGenerator.java

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,34 @@
44
import java.util.HashMap;
55
import java.util.HashSet;
66
import java.util.Map;
7-
import java.util.Optional;
87
import java.util.Set;
98

109
import com.fasterxml.jackson.databind.JsonNode;
1110

12-
import io.swagger.models.Model;
13-
import io.swagger.models.Operation;
14-
import io.swagger.models.Path;
15-
import io.swagger.models.Response;
16-
import io.swagger.models.Swagger;
17-
import io.swagger.models.parameters.BodyParameter;
18-
import io.swagger.models.parameters.Parameter;
19-
import io.swagger.parser.SwaggerParser;
11+
import io.swagger.parser.OpenAPIParser;
12+
import io.swagger.v3.oas.models.OpenAPI;
13+
import io.swagger.v3.oas.models.Operation;
14+
import io.swagger.v3.oas.models.PathItem;
15+
import io.swagger.v3.oas.models.media.Schema;
16+
import io.swagger.v3.oas.models.responses.ApiResponse;
17+
import io.swagger.v3.parser.core.models.ParseOptions;
18+
import io.swagger.v3.parser.core.models.SwaggerParseResult;
19+
import org.apache.commons.lang.*;
2020
import lombok.Getter;
2121
import lombok.extern.slf4j.Slf4j;
2222

2323
@Slf4j
2424
public class BaseJsonSchemaGenerator {
2525

26+
public static final String APPLICATION_JSON = "application/json";
2627
@Getter
2728
protected Map<String, JsonNode> generatedObjects = new HashMap<String, JsonNode>();
2829
protected static final String ORIGINAL_REF = "originalRef";
2930
protected static final String HTTP_JSON_SCHEMA_ORG_DRAFT_04_SCHEMA = "http://json-schema.org/draft-04/schema#";
3031
protected static final String $SCHEMA = "$schema";
31-
protected static final String DEFINITIONS2 = "#/definitions/";
32+
protected static final String DEFINITIONS2 = "#/components/schemas/";
3233
protected static final String TITLE2 = "title";
3334
protected static final String ADDITIONAL_PROPERTIES = "additionalProperties";
34-
protected static final String DEFINITIONS = "definitions";
3535
protected static final String MAX_ITEMS = "maxItems";
3636
protected static final String MIN_ITEMS = "minItems";
3737
protected static final String REQUIRED = "required";
@@ -41,43 +41,58 @@ public class BaseJsonSchemaGenerator {
4141
@Getter
4242
protected Set<String> messageObjects = new HashSet<String>();
4343
@Getter
44-
private Map<String, Model> objectsDefinitions = new HashMap<String, Model>();
44+
private Map<String, Schema> objectsDefinitions = new HashMap<String, Schema>();
4545

4646

47-
protected Swagger readFromInterface20(File interfaceFile) {
48-
49-
Swagger swagger = new SwaggerParser().read(interfaceFile.getAbsolutePath());
50-
objectsDefinitions = swagger.getDefinitions();
51-
for (Map.Entry<String, Path> entry : swagger.getPaths().entrySet()) {
47+
protected void readFromInterface(File interfaceFile) {
48+
ParseOptions po = new ParseOptions();
49+
po.setResolve(true);
50+
SwaggerParseResult result = new OpenAPIParser().readLocation(interfaceFile.getAbsolutePath(),null,po);
51+
OpenAPI swagger = result.getOpenAPI();
52+
Validate.notNull(swagger,"Error during parsing of interface file "+interfaceFile.getAbsolutePath());
53+
objectsDefinitions = swagger.getComponents().getSchemas();
54+
for (Map.Entry<String, PathItem> entry : swagger.getPaths().entrySet()) {
5255
String k = entry.getKey();
53-
Path v = entry.getValue();
54-
log.info(k + "=" + v);
55-
for (Operation op : v.getOperations()) {
56-
log.info("Operation={}", op.getOperationId());
57-
Optional<Parameter> body = op.getParameters().stream().filter(c -> "body".equalsIgnoreCase(c.getIn()))
58-
.findFirst();
59-
if (body.isPresent()) {
60-
BodyParameter bp = (BodyParameter) body.get();
61-
log.info("Request schema={}", bp.getSchema().getReference());
62-
messageObjects.add(bp.getSchema().getReference());
56+
PathItem v = entry.getValue();
57+
analyzeOperation(v);
58+
}
59+
}
6360

64-
}
65-
for (Map.Entry<String, Response> entry2 : op.getResponses().entrySet()) {
66-
String rk = entry2.getKey();
67-
Response r = entry2.getValue();
68-
if (r.getResponseSchema() != null) {
69-
if (r.getResponseSchema().getReference()!=null) {
70-
messageObjects.add(r.getResponseSchema().getReference());
71-
log.info("code={} responseSchema={}", rk, r.getResponseSchema().getReference());
61+
private void analyzeOperation(PathItem v) {
62+
for (Operation op : v.readOperations()) {
63+
log.info("Operation={}", op.getOperationId());
64+
findRequestBodySchema(op, messageObjects);
65+
for (String key : op.getResponses().keySet()){
66+
ApiResponse r = op.getResponses().get(key);
67+
if (r.getContent()!=null) {
68+
if (r.getContent().get(APPLICATION_JSON) != null) {
69+
if (r.getContent().get(APPLICATION_JSON).getSchema().get$ref() != null) {
70+
log.info("code={} responseSchema={}", key, r.getContent().get(APPLICATION_JSON).getSchema().get$ref());
71+
messageObjects.add(r.getContent().get(APPLICATION_JSON).getSchema().get$ref());
7272
} else {
73-
log.warn("code={} response schema is not a referenced definition! type={}",rk,r.getResponseSchema().getClass());
73+
log.warn("code={} response schema is not a referenced definition! type={}", key, r.getContent().get("application/json").getClass());
7474
}
75-
7675
}
7776
}
7877
}
78+
}
79+
}
7980

81+
private void findRequestBodySchema(Operation op, Set<String> messageObjects) {
82+
if (op.getRequestBody()!=null) {
83+
if (op.getRequestBody().getContent().get(APPLICATION_JSON)!=null) {
84+
Schema sc = op.getRequestBody().getContent().get(APPLICATION_JSON).getSchema();
85+
if (sc != null) {
86+
log.info("Request schema={}", sc.get$ref());
87+
if (sc.get$ref()!=null) {
88+
messageObjects.add(sc.get$ref());
89+
} else {
90+
log.warn("Request schema is not a referenced definition!");
91+
}
92+
}
93+
} else {
94+
log.info("No application body of type 'application/json' found for operation {}",op.getOperationId());
95+
}
8096
}
81-
return swagger;
8297
}
8398
}

0 commit comments

Comments
 (0)