Postman Collection Generator (#15294)

* Add Postman generator

* Add Postman generator doc

* Remove contact data

* Change license data

* Add Postman in samples

* Add Postman in bin/configs

* Commit changed files

* Update Postman doc

* Correct generator connfiguration

* Regenerate docs

* Correct javadoc

* Use File instead of FileReader

* Rename to postman-collection (schema) generator

* Commit regenerated files

* Improve help and Javadoc

* Commit regenerated files
This commit is contained in:
Beppe Catanese 2023-05-16 18:51:53 +02:00 committed by GitHub
parent b35ffd3c37
commit ab4a05a959
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 3336 additions and 0 deletions

View File

@ -0,0 +1,4 @@
generatorName: postman-collection
outputDir: samples/schema/postman-collection
inputSpec: modules/openapi-generator/src/test/resources/3_0/postman-collection/SampleProject.yaml
templateDir: modules/openapi-generator/src/main/resources/postman-collection

View File

@ -153,6 +153,7 @@ The following generators are available:
* [graphql-schema](generators/graphql-schema.md)
* [ktorm-schema (beta)](generators/ktorm-schema.md)
* [mysql-schema](generators/mysql-schema.md)
* [postman-collection (beta)](generators/postman-collection.md)
* [protobuf-schema (beta)](generators/protobuf-schema.md)
* [wsdl-schema (beta)](generators/wsdl-schema.md)

View File

@ -0,0 +1,166 @@
---
title: Documentation for the postman-collection Generator
---
## METADATA
| Property | Value | Notes |
| -------- | ----- | ----- |
| generator name | postman-collection | pass this to the generate command after -g |
| generator stability | BETA | |
| generator type | SCHEMA | |
| generator default templating engine | mustache | |
| helpTxt | Generates a Postman collection (format v2.1.0) JSON file | |
## CONFIG OPTIONS
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|folderStrategy|whether to create folders according to the spec’s paths or tags| |null|
|pathParamsAsVariables|whether to create Postman variables for path parameters| |false|
|postmanGuid|whether to convert placeholders (i.e. {{UNIQUE_REFERENCE}}) into Postman formula {{$guid}}| |null|
|postmanGuidPlaceholderName|name of the placeholder (i.e. {{UNIQUE_REFERENCE}}) to replace with Postman formula {{$guid}}| |null|
|postmanIsoTimestamp|whether to convert placeholders (i.e. {{ISO_TIMESTAMP}}) into Postman formula {{$isoTimestamp}}| |null|
|postmanIsoTimestampPlaceholderName|name of the placeholder (i.e. {{ISO_TIMESTAMP}}) to replace with Postman formula {{$isoTimestamp}}| |null|
|postmanVariables|whether to convert placeholders (i.e. {{VAR_1}}) into Postman variables| |null|
|requestParameterGeneration|whether to generate the request parameters based on the schema or the examples| |null|
## IMPORT MAPPING
| Type/Alias | Imports |
| ---------- | ------- |
## INSTANTIATION TYPES
| Type/Alias | Instantiated By |
| ---------- | --------------- |
## LANGUAGE PRIMITIVES
<ul class="column-ul">
</ul>
## RESERVED WORDS
<ul class="column-ul">
</ul>
## FEATURE SET
### Client Modification Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasePath|✗|ToolingExtension
|Authorizations|✗|ToolingExtension
|UserAgent|✗|ToolingExtension
|MockServer|✗|ToolingExtension
### Data Type Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Custom|✗|OAS2,OAS3
|Int32|✓|OAS2,OAS3
|Int64|✓|OAS2,OAS3
|Float|✓|OAS2,OAS3
|Double|✓|OAS2,OAS3
|Decimal|✓|ToolingExtension
|String|✓|OAS2,OAS3
|Byte|✓|OAS2,OAS3
|Binary|✓|OAS2,OAS3
|Boolean|✓|OAS2,OAS3
|Date|✓|OAS2,OAS3
|DateTime|✓|OAS2,OAS3
|Password|✓|OAS2,OAS3
|File|✓|OAS2
|Uuid|✗|
|Array|✓|OAS2,OAS3
|Null|✗|OAS3
|AnyType|✗|OAS2,OAS3
|Object|✓|OAS2,OAS3
|Maps|✓|ToolingExtension
|CollectionFormat|✓|OAS2
|CollectionFormatMulti|✓|OAS2
|Enum|✓|OAS2,OAS3
|ArrayOfEnum|✓|ToolingExtension
|ArrayOfModel|✓|ToolingExtension
|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
|ArrayOfCollectionOfModel|✓|ToolingExtension
|ArrayOfCollectionOfEnum|✓|ToolingExtension
|MapOfEnum|✓|ToolingExtension
|MapOfModel|✓|ToolingExtension
|MapOfCollectionOfPrimitives|✓|ToolingExtension
|MapOfCollectionOfModel|✓|ToolingExtension
|MapOfCollectionOfEnum|✓|ToolingExtension
### Documentation Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Readme|✗|ToolingExtension
|Model|✓|ToolingExtension
|Api|✓|ToolingExtension
### Global Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Host|✓|OAS2,OAS3
|BasePath|✓|OAS2,OAS3
|Info|✓|OAS2,OAS3
|Schemes|✗|OAS2,OAS3
|PartialSchemes|✓|OAS2,OAS3
|Consumes|✓|OAS2
|Produces|✓|OAS2
|ExternalDocumentation|✓|OAS2,OAS3
|Examples|✓|OAS2,OAS3
|XMLStructureDefinitions|✗|OAS2,OAS3
|MultiServer|✗|OAS3
|ParameterizedServer|✗|OAS3
|ParameterStyling|✗|OAS3
|Callbacks|✓|OAS3
|LinkObjects|✗|OAS3
### Parameter Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Path|✓|OAS2,OAS3
|Query|✓|OAS2,OAS3
|Header|✓|OAS2,OAS3
|Body|✓|OAS2
|FormUnencoded|✓|OAS2
|FormMultipart|✓|OAS2
|Cookie|✓|OAS3
### Schema Support Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Simple|✓|OAS2,OAS3
|Composite|✓|OAS2,OAS3
|Polymorphism|✓|OAS2,OAS3
|Union|✗|OAS3
|allOf|✗|OAS2,OAS3
|anyOf|✗|OAS3
|oneOf|✗|OAS3
|not|✗|OAS3
### Security Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect|✓|OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3
|OAuth2_ClientCredentials|✓|OAS2,OAS3
|OAuth2_AuthorizationCode|✓|OAS2,OAS3
### Wire Format Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|JSON|✓|OAS2,OAS3
|XML|✓|OAS2,OAS3
|PROTOBUF|✗|ToolingExtension
|Custom|✗|OAS2,OAS3

166
docs/generators/postman.md Normal file
View File

@ -0,0 +1,166 @@
---
title: Documentation for the postman Generator
---
## METADATA
| Property | Value | Notes |
| -------- | ----- | ----- |
| generator name | postman | pass this to the generate command after -g |
| generator stability | BETA | |
| generator type | DOCUMENTATION | |
| generator default templating engine | mustache | |
| helpTxt | Generates a postman JSON file | |
## CONFIG OPTIONS
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|folderStrategy|whether to create folders according to the spec&rsquo;s paths or tags| |null|
|pathParamsAsVariables|whether to create Postman variables for path parameters| |false|
|postmanGuid|whether to convert placeholders (i.e. {{UNIQUE_REFERENCE}}) into Postman formula {{$guid}}| |null|
|postmanGuidPlaceholderName|name of the placeholder (i.e. {{UNIQUE_REFERENCE}}) to replace with Postman formula {{$guid}}| |null|
|postmanIsoTimestamp|whether to convert placeholders (i.e. {{ISO_TIMESTAMP}}) into Postman formula {{$isoTimestamp}}| |null|
|postmanIsoTimestampPlaceholderName|name of the placeholder (i.e. {{ISO_TIMESTAMP}}) to replace with Postman formula {{$isoTimestamp}}| |null|
|postmanVariables|whether to convert placeholders (i.e. {{VAR_1}}) into Postman variables| |null|
|requestParameterGeneration|whether to generate the request parameters based on the schema or the examples| |null|
## IMPORT MAPPING
| Type/Alias | Imports |
| ---------- | ------- |
## INSTANTIATION TYPES
| Type/Alias | Instantiated By |
| ---------- | --------------- |
## LANGUAGE PRIMITIVES
<ul class="column-ul">
</ul>
## RESERVED WORDS
<ul class="column-ul">
</ul>
## FEATURE SET
### Client Modification Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasePath|✗|ToolingExtension
|Authorizations|✗|ToolingExtension
|UserAgent|✗|ToolingExtension
|MockServer|✗|ToolingExtension
### Data Type Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Custom|✗|OAS2,OAS3
|Int32|✓|OAS2,OAS3
|Int64|✓|OAS2,OAS3
|Float|✓|OAS2,OAS3
|Double|✓|OAS2,OAS3
|Decimal|✓|ToolingExtension
|String|✓|OAS2,OAS3
|Byte|✓|OAS2,OAS3
|Binary|✓|OAS2,OAS3
|Boolean|✓|OAS2,OAS3
|Date|✓|OAS2,OAS3
|DateTime|✓|OAS2,OAS3
|Password|✓|OAS2,OAS3
|File|✓|OAS2
|Uuid|✗|
|Array|✓|OAS2,OAS3
|Null|✗|OAS3
|AnyType|✗|OAS2,OAS3
|Object|✓|OAS2,OAS3
|Maps|✓|ToolingExtension
|CollectionFormat|✓|OAS2
|CollectionFormatMulti|✓|OAS2
|Enum|✓|OAS2,OAS3
|ArrayOfEnum|✓|ToolingExtension
|ArrayOfModel|✓|ToolingExtension
|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
|ArrayOfCollectionOfModel|✓|ToolingExtension
|ArrayOfCollectionOfEnum|✓|ToolingExtension
|MapOfEnum|✓|ToolingExtension
|MapOfModel|✓|ToolingExtension
|MapOfCollectionOfPrimitives|✓|ToolingExtension
|MapOfCollectionOfModel|✓|ToolingExtension
|MapOfCollectionOfEnum|✓|ToolingExtension
### Documentation Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Readme|✗|ToolingExtension
|Model|✓|ToolingExtension
|Api|✓|ToolingExtension
### Global Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Host|✓|OAS2,OAS3
|BasePath|✓|OAS2,OAS3
|Info|✓|OAS2,OAS3
|Schemes|✗|OAS2,OAS3
|PartialSchemes|✓|OAS2,OAS3
|Consumes|✓|OAS2
|Produces|✓|OAS2
|ExternalDocumentation|✓|OAS2,OAS3
|Examples|✓|OAS2,OAS3
|XMLStructureDefinitions|✗|OAS2,OAS3
|MultiServer|✗|OAS3
|ParameterizedServer|✗|OAS3
|ParameterStyling|✗|OAS3
|Callbacks|✓|OAS3
|LinkObjects|✗|OAS3
### Parameter Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Path|✓|OAS2,OAS3
|Query|✓|OAS2,OAS3
|Header|✓|OAS2,OAS3
|Body|✓|OAS2
|FormUnencoded|✓|OAS2
|FormMultipart|✓|OAS2
|Cookie|✓|OAS3
### Schema Support Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|Simple|✓|OAS2,OAS3
|Composite|✓|OAS2,OAS3
|Polymorphism|✓|OAS2,OAS3
|Union|✗|OAS3
|allOf|✗|OAS2,OAS3
|anyOf|✗|OAS3
|oneOf|✗|OAS3
|not|✗|OAS3
### Security Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|BasicAuth|✓|OAS2,OAS3
|ApiKey|✓|OAS2,OAS3
|OpenIDConnect|✗|OAS3
|BearerToken|✓|OAS3
|OAuth2_Implicit|✓|OAS2,OAS3
|OAuth2_Password|✓|OAS2,OAS3
|OAuth2_ClientCredentials|✓|OAS2,OAS3
|OAuth2_AuthorizationCode|✓|OAS2,OAS3
### Wire Format Feature
| Name | Supported | Defined By |
| ---- | --------- | ---------- |
|JSON|✓|OAS2,OAS3
|XML|✓|OAS2,OAS3
|PROTOBUF|✗|ToolingExtension
|Custom|✗|OAS2,OAS3

View File

@ -0,0 +1,844 @@
package org.openapitools.codegen.languages;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.v3.core.util.Json;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.examples.Example;
import io.swagger.v3.oas.models.servers.ServerVariable;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* OpenAPI generator for Postman Collection format v2.1
*/
public class PostmanCollectionCodegen extends DefaultCodegen implements CodegenConfig {
private final Logger LOGGER = LoggerFactory.getLogger(PostmanCollectionCodegen.class);
protected String apiVersion = "1.0.0";
// Select whether to create folders according to the specs paths or tags. Values: Paths | Tags
public static final String FOLDER_STRATEGY = "folderStrategy";
public static final String FOLDER_STRATEGY_DEFAULT_VALUE = "Tags";
// Select whether to create Postman variables for path templates
public static final String PATH_PARAMS_AS_VARIABLES = "pathParamsAsVariables";
public static final Boolean PATH_PARAMS_AS_VARIABLES_DEFAULT_VALUE = true;
public static final String POSTMAN_FILE_DEFAULT_VALUE = "postman.json";
// create Postman variables from placeholders ie {{VAR_1}}
public static final String POSTMAN_VARIABLES = "postmanVariables";
protected Boolean postmanVariables = true;
// replace placeholder `UNIQUE_REFERENCE` with Postman {{$guid}}
public static final String POSTMAN_GUID = "postmanGuid";
protected Boolean postmanGuid = true;
// default guid placeholder name
public static final String POSTMAN_GUID_PLACEHOLDER_NAME = "postmanGuidPlaceholderName";
protected static final String POSTMAN_GUID_PLACEHOLDER_NAME_DEFAULT_VALUE = "UNIQUE_REFERENCE";
protected static String postmanGuidPlaceholderName = POSTMAN_GUID_PLACEHOLDER_NAME_DEFAULT_VALUE;
// replace placeholder `ISO_TIMESTAMP` with Postman {{isoTimestamp}}
protected Boolean postmanIsoTimestamp = true;
public static final String POSTMAN_ISO_TIMESTAMP = "postmanIsoTimestamp";
public static final String POSTMAN_ISO_TIMESTAMP_PLACEHOLDER_NAME = "postmanIsoTimestampPlaceholderName";
public static final String POSTMAN_ISO_TIMESTAMP_PLACEHOLDER_NAME_DEFAULT_VALUE = "ISO_TIMESTAMP";
protected static String postmanIsoTimestampPlaceholderName = POSTMAN_ISO_TIMESTAMP_PLACEHOLDER_NAME_DEFAULT_VALUE;
public static final String REQUEST_PARAMETER_GENERATION = "requestParameterGeneration";
public static final String REQUEST_PARAMETER_GENERATION_DEFAULT_VALUE = "Example";
public String folderStrategy = FOLDER_STRATEGY_DEFAULT_VALUE; // values: Paths | Tags
protected Boolean pathParamsAsVariables = PATH_PARAMS_AS_VARIABLES_DEFAULT_VALUE; // values: true | false
// Output file
public String postmanFile = POSTMAN_FILE_DEFAULT_VALUE;
// Select whether to generate requests/responses from Example or Schema
protected String requestParameterGeneration = REQUEST_PARAMETER_GENERATION_DEFAULT_VALUE; // values: Example, Schema
public Set<PostmanVariable> variables = new HashSet<>();
public static final String JSON_ESCAPE_DOUBLE_QUOTE = "\\\"";
public static final String JSON_ESCAPE_NEW_LINE = "\\n";
// operations grouped by tag
protected Map<String, List<CodegenOperation>> codegenOperationsByTag = new HashMap<>();
// list of operations
protected List<CodegenOperation> codegenOperationsList = new ArrayList<>();
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see org.openapitools.codegen.CodegenType
*/
public CodegenType getTag() {
return CodegenType.SCHEMA;
}
@Override
public GeneratorLanguage generatorLanguage() {
return null;
}
/**
* Configures a friendly name for the generator. This will be used by the generator
* to select the library with the -g flag.
*
* @return the friendly name for the generator
*/
public String getName() {
return "postman-collection";
}
public PostmanCollectionCodegen() {
super();
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.BETA)
.build();
embeddedTemplateDir = templateDir = "postman-collection";
supportingFiles.add(
new SupportingFile("postman.mustache", "", postmanFile)
);
cliOptions.clear();
cliOptions.add(CliOption.newString(FOLDER_STRATEGY, "whether to create folders according to the specs paths or tags"));
cliOptions.add(CliOption.newBoolean(PATH_PARAMS_AS_VARIABLES, "whether to create Postman variables for path parameters"));
cliOptions.add(CliOption.newString(POSTMAN_VARIABLES, "whether to convert placeholders (i.e. {{VAR_1}}) into Postman variables"));
cliOptions.add(CliOption.newString(POSTMAN_GUID, "whether to convert placeholders (i.e. {{UNIQUE_REFERENCE}}) into Postman formula {{$guid}}"));
cliOptions.add(CliOption.newString(POSTMAN_GUID_PLACEHOLDER_NAME, "name of the placeholder (i.e. {{UNIQUE_REFERENCE}}) to replace with Postman formula {{$guid}}"));
cliOptions.add(CliOption.newString(POSTMAN_ISO_TIMESTAMP, "whether to convert placeholders (i.e. {{ISO_TIMESTAMP}}) into Postman formula {{$isoTimestamp}}"));
cliOptions.add(CliOption.newString(POSTMAN_ISO_TIMESTAMP_PLACEHOLDER_NAME, "name of the placeholder (i.e. {{ISO_TIMESTAMP}}) to replace with Postman formula {{$isoTimestamp}}"));
cliOptions.add(CliOption.newString(REQUEST_PARAMETER_GENERATION, "whether to generate the request parameters based on the schema or the examples"));
}
@Override
public void postProcessParameter(CodegenParameter parameter) {
if(pathParamsAsVariables && parameter.isPathParam) {
variables.add(new PostmanVariable()
.addName(parameter.paramName)
.addType(mapToPostmanType(parameter.dataType))
.addExample(parameter.example));
}
}
@Override
public void preprocessOpenAPI(OpenAPI openAPI) {
super.preprocessOpenAPI(openAPI);
this.additionalProperties().put("formattedDescription", formatDescription(openAPI.getInfo().getDescription()));
}
@Override
public List<CodegenServerVariable> fromServerVariables(Map<String, ServerVariable> variables) {
if(variables != null){
variables.entrySet().stream().forEach(serverVariableEntry -> this.variables.add(new PostmanVariable()
.addName(serverVariableEntry.getKey())
.addType("string")
.addExample(serverVariableEntry.getValue().getDefault())));
}
return super.fromServerVariables(variables);
}
@Override
public void processOpts() {
super.processOpts();
if(additionalProperties().containsKey(FOLDER_STRATEGY)) {
folderStrategy = additionalProperties().get(FOLDER_STRATEGY).toString();
}
if (additionalProperties.containsKey(PATH_PARAMS_AS_VARIABLES)) {
pathParamsAsVariables = Boolean.parseBoolean(additionalProperties.get(PATH_PARAMS_AS_VARIABLES).toString());
}
if(additionalProperties().containsKey(REQUEST_PARAMETER_GENERATION)) {
requestParameterGeneration = additionalProperties().get(REQUEST_PARAMETER_GENERATION).toString();
}
if(additionalProperties().containsKey(POSTMAN_VARIABLES)) {
postmanVariables = Boolean.parseBoolean(additionalProperties.get(POSTMAN_VARIABLES).toString());
}
if(additionalProperties().containsKey(POSTMAN_GUID)) {
postmanGuid = Boolean.parseBoolean(additionalProperties.get(POSTMAN_GUID).toString());
}
if(additionalProperties().containsKey(POSTMAN_GUID_PLACEHOLDER_NAME)) {
postmanGuidPlaceholderName = additionalProperties.get(POSTMAN_GUID_PLACEHOLDER_NAME).toString();
}
if(additionalProperties().containsKey(POSTMAN_ISO_TIMESTAMP)) {
postmanIsoTimestamp = Boolean.parseBoolean(additionalProperties.get(POSTMAN_ISO_TIMESTAMP).toString());
}
if(additionalProperties().containsKey(POSTMAN_ISO_TIMESTAMP_PLACEHOLDER_NAME)) {
postmanIsoTimestampPlaceholderName = additionalProperties.get(POSTMAN_ISO_TIMESTAMP_PLACEHOLDER_NAME).toString();
}
super.vendorExtensions().put("variables", variables);
if(folderStrategy.equalsIgnoreCase("tags")) {
this.additionalProperties().put("codegenOperationsByTag", codegenOperationsByTag);
} else {
this.additionalProperties().put("codegenOperationsList", codegenOperationsList);
}
}
/**
* Process and modify operations before generating code
*/
@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
OperationsMap results = super.postProcessOperationsWithModels(objs, allModels);
OperationMap ops = results.getOperations();
List<CodegenOperation> opList = ops.getOperation();
for(CodegenOperation codegenOperation : opList) {
if(pathParamsAsVariables) {
codegenOperation.path = doubleCurlyBraces(codegenOperation.path);
}
codegenOperation.summary = getSummary(codegenOperation);
// request headers
if(codegenOperation.produces != null && codegenOperation.produces.get(0) != null) {
// produces mediaType as `Accept` header (use first mediaType only)
String mediaType = codegenOperation.produces.get(0).get("mediaType");
CodegenParameter acceptHeader = new CodegenParameter();
acceptHeader.paramName = "Accept";
CodegenProperty schema = new CodegenProperty();
schema.defaultValue = mediaType;
acceptHeader.setSchema(schema);
codegenOperation.headerParams.add(0, acceptHeader);
}
if(codegenOperation.consumes != null && codegenOperation.consumes.get(0) != null) {
// consumes mediaType as `Content-Type` header (use first mediaType only)
String mediaType = codegenOperation.consumes.get(0).get("mediaType");
CodegenParameter contentTypeHeader = new CodegenParameter();
contentTypeHeader.paramName = "Content-Type";
CodegenProperty schema = new CodegenProperty();
schema.defaultValue = mediaType;
contentTypeHeader.setSchema(schema);
codegenOperation.headerParams.add(0, contentTypeHeader);
}
// build pathSegments
String[] pathSegments = codegenOperation.path.substring(1).split("/");
codegenOperation.vendorExtensions.put("pathSegments", pathSegments);
codegenOperation.responses.stream().forEach(r -> r.vendorExtensions.put("pathSegments", pathSegments));
List<PostmanRequestItem> postmanRequests = getPostmanRequests(codegenOperation);
if(postmanRequests != null) {
if(postmanVariables) {
postmanRequests = createPostmanVariables(postmanRequests);
}
if(postmanGuid) {
postmanRequests = setPostmanGuid(postmanRequests);
}
if(postmanIsoTimestamp) {
postmanRequests = setPostmanIsoTimestamp(postmanRequests);
}
codegenOperation.vendorExtensions.put("postmanRequests", postmanRequests);
}
// set all available responses
for(CodegenResponse codegenResponse : codegenOperation.responses) {
codegenResponse.vendorExtensions.put("status", getStatus(codegenResponse));
// TODO: set response for each request
// if(postmanRequests != null) {
// // re-use request body for each response
// codegenResponse.vendorExtensions.put("requestBody", postmanRequests);
// }
// String responseBody = getResponseBody(codegenResponse);
// if(responseBody != null) {
// codegenResponse.vendorExtensions.put("responseBody", responseBody);
// codegenResponse.vendorExtensions.put("hasResponseBody", true);
// } else {
// codegenResponse.vendorExtensions.put("hasResponseBody", false);
// }
}
if(folderStrategy.equalsIgnoreCase("tags")) {
addToMap(codegenOperation);
} else {
addToList(codegenOperation);
}
}
return results;
}
/**
* Add the CodegenOperation to the map that is passed to the Mustache templates
* The map groups the CodegenOperations by tag as defined in the OpenAPI spec
* @param codegenOperation Codegen operation instance
*/
void addToMap(CodegenOperation codegenOperation){
String key = null;
if(codegenOperation.tags == null || codegenOperation.tags.isEmpty()) {
key = "default";
} else {
key = codegenOperation.tags.get(0).getName();
}
List<CodegenOperation> list = codegenOperationsByTag.get(key);
if(list == null) {
list = new ArrayList<>();
}
list.add(codegenOperation);
codegenOperationsByTag.put(key, list);
}
void addToList(CodegenOperation codegenOperation) {
codegenOperationsList.add(codegenOperation);
}
String getResponseBody(CodegenResponse codegenResponse) {
String responseBody = "";
if(codegenResponse.getContent() != null && codegenResponse.getContent().get("application/json") != null &&
codegenResponse.getContent().get("application/json").getExamples() != null) {
// find in components/examples
String exampleRef = codegenResponse.getContent().get("application/json").getExamples()
.values().iterator().next().get$ref();
if(exampleRef != null) {
Example example = this.openAPI.getComponents().getExamples().get(extractExampleByName(exampleRef));
responseBody = getJsonFromExample(example);
}
} else if(codegenResponse.getContent() != null) {
// find in context examples
Map<String, Example> maxExamples = codegenResponse.getContent().get("application/json").getExamples();
if(maxExamples != null && maxExamples.values().iterator().hasNext()) {
responseBody = getJsonFromExample(maxExamples.values().iterator().next());
}
}
return responseBody;
}
// from OpenAPI operation to n Postman requests
List<PostmanRequestItem> getPostmanRequests(CodegenOperation codegenOperation) {
List<PostmanRequestItem> items = new ArrayList<>();
if(codegenOperation.getHasBodyParam()) {
// operation with bodyParam
if (requestParameterGeneration.equalsIgnoreCase("Schema")) {
// get from schema
items.add(new PostmanRequestItem(codegenOperation.summary, getJsonFromSchema(codegenOperation.bodyParam)));
} else {
// get from examples
if (codegenOperation.bodyParam.example != null) {
// find in bodyParam example
items.add(new PostmanRequestItem(codegenOperation.summary, formatJson(codegenOperation.bodyParam.example)));
} else if (codegenOperation.bodyParam.getContent().get("application/json") != null &&
codegenOperation.bodyParam.getContent().get("application/json").getExamples() != null) {
// find in components/examples
for (Map.Entry<String, Example> entry : codegenOperation.bodyParam.getContent().get("application/json").getExamples().entrySet()) {
String exampleRef = entry.getValue().get$ref();
Example example = this.openAPI.getComponents().getExamples().get(extractExampleByName(exampleRef));
String exampleAsString = getJsonFromExample(example);
items.add(new PostmanRequestItem(example.getSummary(), exampleAsString));
}
} else if (codegenOperation.bodyParam.getSchema() != null) {
// find in schema example
String exampleAsString = formatJson(codegenOperation.bodyParam.getSchema().getExample());
items.add(new PostmanRequestItem(codegenOperation.summary, exampleAsString));
} else {
// example not found
// get from schema
items.add(new PostmanRequestItem(codegenOperation.summary, getJsonFromSchema(codegenOperation.bodyParam)));
}
}
} else {
// operation without bodyParam
items.add(new PostmanRequestItem(codegenOperation.summary, ""));
}
return items;
}
// from placeholders (ie {{VAR_1}}) create Postman variables
public List<PostmanRequestItem> createPostmanVariables(List<PostmanRequestItem> postmanRequests) {
for(PostmanRequestItem requestItem : postmanRequests) {
for(String var: extractPlaceholders(requestItem.getBody())) {
variables.add(new PostmanVariable()
.addName(var)
.addType("string")
.addExample(""));
}
}
return postmanRequests;
}
// replace postmanGuid placeholder (ie {{UNIQUE_REFERENCE}}) with Postman formula {{$guid}}
List<PostmanRequestItem> setPostmanGuid(List<PostmanRequestItem> postmanRequests) {
for(PostmanRequestItem requestItem : postmanRequests) {
requestItem.setBody(requestItem.getBody().replace("{{" + postmanGuidPlaceholderName + "}}", "{{$guid}}"));
}
return postmanRequests;
}
// replace postman placeholder (ie {{ISO_TIMESTAMP}}) with Postman formula {{$isoTimestamp}}
List<PostmanRequestItem> setPostmanIsoTimestamp(List<PostmanRequestItem> postmanRequests) {
for(PostmanRequestItem requestItem : postmanRequests) {
requestItem.setBody(requestItem.getBody().replace("{{" + postmanIsoTimestampPlaceholderName + "}}", "{{$isoTimestamp}}"));
}
return postmanRequests;
}
/**
* Returns human-friendly help for the generator. Provide the consumer with help
* tips, parameters here
*
* @return A string value for the help message
*/
public String getHelp() {
return "Generates a Postman collection (format v2.1.0) JSON file";
}
/**
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
* those terms here. This logic is only called if a variable matches the reserved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
}
/**
* override with any special text escaping logic to handle unsafe
* characters so as to avoid code injection
*
* @param input String to be cleaned up
* @return string with unsafe characters removed or escaped
*/
@Override
public String escapeUnsafeCharacters(String input) {
//TODO: check that this logic is safe to escape unsafe characters to avoid code injection
return input;
}
/**
* Escape single and/or double quote to avoid code injection
*
* @param input String to be cleaned up
* @return string with quotation mark removed or escaped
*/
public String escapeQuotationMark(String input) {
//TODO: check that this logic is safe to escape quotation mark to avoid code injection
return input.replace("\"", "\\\"");
}
public String doubleCurlyBraces(String str) {
// remove doublebraces first
String s = str.replace("{{", "{").replace("}}", "}");
// change all singlebraces to doublebraces
s = s.replace("{", "{{").replace("}", "}}");
return s;
}
public String extractExampleByName(String ref) {
return ref.substring(ref.lastIndexOf("/") + 1);
}
public String mapToPostmanType(String openApiDataType) {
String ret = "any"; // default value
if(openApiDataType.equalsIgnoreCase("string")) {
ret = "string";
} else if(openApiDataType.equalsIgnoreCase("number") ||
openApiDataType.equalsIgnoreCase("integer")) {
ret = "number";
} else if(openApiDataType.equalsIgnoreCase("boolean")) {
ret = "boolean";
}
return ret;
}
/**
* get HTTP Status Code as text
* @param codegenResponse
* @return
*/
String getStatus(CodegenResponse codegenResponse) {
String ret = "";
if (codegenResponse.is2xx) {
if (codegenResponse.code.equalsIgnoreCase("200")) {
ret = "OK";
} else if (codegenResponse.code.equalsIgnoreCase("201")) {
ret = "Created";
} else {
ret = "Success";
}
} else if (codegenResponse.is3xx) {
ret = "Redirection";
}
if (codegenResponse.is4xx) {
if (codegenResponse.code.equalsIgnoreCase("400")) {
ret = "Bad Request";
} else if (codegenResponse.code.equalsIgnoreCase("401")) {
ret = "Unauthorized";
} else if (codegenResponse.code.equalsIgnoreCase("403")) {
ret = "Forbidden";
} else if (codegenResponse.code.equalsIgnoreCase("404")) {
ret = "Not Found";
} else if (codegenResponse.code.equalsIgnoreCase("409")) {
ret = "Conflict";
} else {
ret = "Client Error";
}
}
if (codegenResponse.is5xx) {
if (codegenResponse.code.equalsIgnoreCase("500")) {
ret = "Internal Server Error";
} else if (codegenResponse.code.equalsIgnoreCase("501")) {
ret = "Not Implemented";
} else {
ret = "Server Error";
}
}
return ret;
}
// make sure operation name is always set
String getSummary(CodegenOperation codegenOperation) {
String ret = null;
if(codegenOperation.summary != null) {
ret = codegenOperation.summary;
} else if (codegenOperation.operationId != null) {
ret = codegenOperation.operationId;
} else {
ret = codegenOperation.httpMethod;
}
return ret;
}
/**
* Format text to include in JSON file
* @param description Text to format
* @return Formatted text
*/
public String formatDescription(String description) {
description = description.replace("\n", JSON_ESCAPE_NEW_LINE);
description = description.replace("\"", JSON_ESCAPE_DOUBLE_QUOTE);
return description;
}
/**
* Extract all placeholders (string delimited by curly braces ie {{PLACEHOLDER}}) from the input string
* @param input String containing the placeholders
* @return Set of placeholders found in the string
*/
public Set<String> extractPlaceholders(String input) {
Set<String> variables = new HashSet<>();
Pattern pattern = Pattern.compile("\\{\\{([^}]*)\\}\\}");
Matcher matcher = pattern.matcher(input);
while(matcher.find()) {
if(postmanGuidPlaceholderName.equalsIgnoreCase(matcher.group(1))) {
// skip if it is postmanGuid placeholder
break;
}
if(postmanIsoTimestampPlaceholderName.equalsIgnoreCase(matcher.group(1))) {
// skip if it is postmanIsoTimestamp placeholder
break;
}
if(isPostmanDynamicVariable(matcher.group(1))) {
// skip if it is reserved words
break;
}
variables.add(matcher.group(1));
}
return variables;
}
public boolean isPostmanDynamicVariable(String value) {
boolean ret = false;
if(value.equals("$guid") || value.equals("$timestamp")) {
ret = true;
}
return ret;
}
// Supporting helpers
public String getJsonFromSchema(CodegenParameter codegenParameter) {
String ret = "{" + JSON_ESCAPE_NEW_LINE + " ";
int numVars = codegenParameter.vars.size();
int counter = 1;
for (CodegenProperty codegenProperty : codegenParameter.vars) {
ret = ret + JSON_ESCAPE_DOUBLE_QUOTE + codegenProperty.baseName + JSON_ESCAPE_DOUBLE_QUOTE + ": " +
JSON_ESCAPE_DOUBLE_QUOTE + "<" + getPostmanType(codegenProperty) + ">" + JSON_ESCAPE_DOUBLE_QUOTE;
if(counter < numVars) {
// add comma unless last attribute
ret = ret + "," + JSON_ESCAPE_NEW_LINE + " ";
}
counter++;
}
ret = ret + JSON_ESCAPE_NEW_LINE + "}";
return ret;
}
public String getJsonFromExample(Example example) {
String ret = "";
if(example == null) {
return ret;
}
if(example.getValue() instanceof ObjectNode) {
ret = convertToJson((ObjectNode)example.getValue());
} else if(example.getValue() instanceof LinkedHashMap) {
ret = convertToJson((LinkedHashMap)example.getValue());
}
return ret;
}
// array of attributes from JSON payload (ignore commas within quotes)
public String[] getAttributes(String json) {
return json.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
}
public String convertToJson(ObjectNode objectNode) {
return formatJson(objectNode.toString());
}
// convert to JSON (string) escaping and formatting
public String convertToJson(LinkedHashMap<String, Object> linkedHashMap) {
String ret = "";
return traverseMap(linkedHashMap, ret);
}
public String formatJson(String json) {
ObjectMapper objectMapper = new ObjectMapper();
try {
// convert to JSON object and prettify
JsonNode actualObj = objectMapper.readTree(json);
json = Json.pretty(actualObj);
json = json.replace("\"", JSON_ESCAPE_DOUBLE_QUOTE);
json = json.replace("\n", JSON_ESCAPE_NEW_LINE);
} catch (JsonProcessingException e) {
LOGGER.warn("Error formatting JSON", e);
json = "";
}
return json;
}
// traverse recursively
private String traverseMap(LinkedHashMap<String, Object> linkedHashMap, String ret) {
ret = ret + "{" + JSON_ESCAPE_NEW_LINE + " ";
int numVars = linkedHashMap.entrySet().size();
int counter = 1;
for (Map.Entry<String, Object> mapElement : linkedHashMap.entrySet()) {
String key = mapElement.getKey();
Object value = mapElement.getValue();
if(value instanceof String) {
// unescape double quotes already escaped
value = ((String)value).replace("\\\"", "\"");
ret = ret + JSON_ESCAPE_DOUBLE_QUOTE + key + JSON_ESCAPE_DOUBLE_QUOTE + ": " +
JSON_ESCAPE_DOUBLE_QUOTE + value + JSON_ESCAPE_DOUBLE_QUOTE;
} else if (value instanceof Integer) {
ret = ret + JSON_ESCAPE_DOUBLE_QUOTE + key + JSON_ESCAPE_DOUBLE_QUOTE + ": " +
value;
} else if (value instanceof LinkedHashMap) {
String in = ret + JSON_ESCAPE_DOUBLE_QUOTE + key + JSON_ESCAPE_DOUBLE_QUOTE + ": ";
ret = traverseMap(((LinkedHashMap<String, Object>) value), in);
} else {
LOGGER.warn("Value type unrecognised: " + value.getClass());
}
if(counter < numVars) {
// add comma unless last attribute
ret = ret + "," + JSON_ESCAPE_NEW_LINE + " ";
}
counter++;
}
ret = ret + JSON_ESCAPE_NEW_LINE + "}";
return ret;
}
public String getPostmanType(CodegenProperty codegenProperty) {
if(codegenProperty.isNumeric) {
return "number";
} else if(codegenProperty.isDate) {
return "date";
} else {
return "string";
}
}
// Supporting models
public class PostmanRequestItem {
private String name;
private String body;
public PostmanRequestItem() {
}
public PostmanRequestItem(String name, String body) {
this.name = name;
this.body = body;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
class PostmanVariable {
private String name;
private String type;
private String example;
public PostmanVariable addName(String name) {
this.name = name;
return this;
}
public PostmanVariable addType(String type) {
this.type = type;
return this;
}
public PostmanVariable addExample(String example) {
this.example = example;
return this;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PostmanVariable that = (PostmanVariable) o;
return name.equals(that.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public String toString() {
return "PostmanVariable{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
", example='" + example + '\'' +
'}';
}
}
}

View File

@ -98,6 +98,7 @@ org.openapitools.codegen.languages.PhpSlim4ServerCodegen
org.openapitools.codegen.languages.PhpSymfonyServerCodegen
org.openapitools.codegen.languages.PhpMezzioPathHandlerServerCodegen
org.openapitools.codegen.languages.PhpDataTransferClientCodegen
org.openapitools.codegen.languages.PostmanCollectionCodegen
org.openapitools.codegen.languages.PowerShellClientCodegen
org.openapitools.codegen.languages.ProtobufSchemaCodegen
org.openapitools.codegen.languages.PythonClientCodegen

View File

@ -0,0 +1,60 @@
{
"name": "{{path}}{{#isDeprecated}} (DEPRECATED){{/isDeprecated}}",
"description": "{{{notes}}}",
"item": [
{{#vendorExtensions.postmanRequests}}
{
"name": "{{name}}",
"request": {
"method": "{{httpMethod}}",
"header": [
{{#headerParams}}
{
"key": "{{paramName}}",
"value": "{{schema.defaultValue}}"
}{{^-last}},{{/-last}}
{{/headerParams}}
],
"body": {
"mode": "raw",
"raw": "{{{body}}}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{=<% %>=}}{{baseUrl}}<%={{ }}=%>{{path}}",
"host": [
"{{=<% %>=}}{{baseUrl}}<%={{ }}=%>"
],
"path": [
{{#vendorExtensions.pathSegments}}
"{{.}}"{{^-last}},{{/-last}}
{{/vendorExtensions.pathSegments}}
],
"variable": [
{{#pathParams}}
{
"key": "{{paramName}}",
"value": "",
"description": "{{description}}"
}{{^-last}},{{/-last}}
{{/pathParams}}
],
"query": [
{{#queryParams}}
{
"key": "{{paramName}}",
"value": "{{example}}"
}{{^-last}},{{/-last}}
{{/queryParams}}
]
},
"description": "{{{notes}}}"
}
}{{^-last}},{{/-last}}
{{/vendorExtensions.postmanRequests}}
]
}

View File

@ -0,0 +1,74 @@
{
"info": {
"name": "{{{appName}}}",
"description": {
"content": "{{{formattedDescription}}}",
"type": "text/markdown"
},
"version": "{{{appVersion}}}",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{{#codegenOperationsByTag}}
{{#entrySet}}
{
"name": "{{key}}",
"item": [{{#value}}
{{>item}}{{^-last}},{{/-last}}{{/value}}
]
}{{^-last}},{{/-last}}
{{/entrySet}}
{{/codegenOperationsByTag}}
{{#codegenOperationsList}}
{{>item}}{{^-last}},{{/-last}}
{{/codegenOperationsList}}
],
{{#authMethods}}{{#-first}}{{#isApiKey}}"auth": {
"type": "apikey",
"apikey": [
{
"key": "value",
"value": "{{=<% %>=}}{{<%={{ }}=%>{{keyParamName}}{{=<% %>=}}}}<%={{ }}=%>",
"type": "string"
},
{
"key": "key",
"value": "{{keyParamName}}",
"type": "string"
}
]
},{{/isApiKey}}{{#isBasic}}"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "{{=<% %>=}}{{<%={{ }}=%>USERNAME{{=<% %>=}}}}<%={{ }}=%>",
"type": "string"
},
{
"key": "password",
"value": "{{=<% %>=}}{{<%={{ }}=%>PASSWORD{{=<% %>=}}}}<%={{ }}=%>",
"type": "string"
}
]
},{{/isBasic}}{{/-first}}{{/authMethods}}
"variable": [{{#servers}}{{#-first}}
{
"key": "baseUrl",
"value": "{{url}}",
"type": "string"
}{{/-first}}{{/servers}}{{#authMethods}}{{#isApiKey}},
{
"key": "{{keyParamName}}",
"value": "",
"type": "string"
}{{/isApiKey}}{{/authMethods}}{{#apiInfo}}{{#apis}}{{#vendorExtensions}}{{#-first}}{{#variables}}{{#-first}},{{/-first}}
{
{{! use first element in vendorExtensions }}
"key": "{{name}}",
"value": "{{example}}",
"type": "{{type}}"
}{{^-last}},{{/-last}}{{/variables}}{{/-first}}{{/vendorExtensions}}{{/apis}}{{/apiInfo}}
]
}

View File

@ -0,0 +1,646 @@
package org.openapitools.codegen.postman;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Assert;
import org.junit.Test;
import org.openapitools.codegen.ClientOptInput;
import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.DefaultGenerator;
import org.openapitools.codegen.config.CodegenConfigurator;
import org.openapitools.codegen.languages.PostmanCollectionCodegen;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.openapitools.codegen.TestUtils.*;
public class PostmanCollectionCodegenTest {
@Test
public void testInitialConfigValues() throws Exception {
final PostmanCollectionCodegen postmanCollectionCodegen = new PostmanCollectionCodegen();
postmanCollectionCodegen.processOpts();
Assert.assertEquals(postmanCollectionCodegen.folderStrategy, "Tags");
Assert.assertEquals(postmanCollectionCodegen.postmanFile, "postman.json");
Assert.assertNull(postmanCollectionCodegen.additionalProperties().get("codegenOperationsList"));
Assert.assertNotNull(postmanCollectionCodegen.additionalProperties().get("codegenOperationsByTag"));
}
@Test
public void testConfigWithFolderStrategyTags() throws Exception {
final PostmanCollectionCodegen postmanCollectionCodegen = new PostmanCollectionCodegen();
postmanCollectionCodegen.additionalProperties().put(postmanCollectionCodegen.FOLDER_STRATEGY, "Tags");
postmanCollectionCodegen.processOpts();
Assert.assertEquals(postmanCollectionCodegen.folderStrategy, "Tags");
Assert.assertNull(postmanCollectionCodegen.additionalProperties().get("codegenOperationsList"));
Assert.assertNotNull(postmanCollectionCodegen.additionalProperties().get("codegenOperationsByTag"));
}
@Test
public void testBasicGeneration() throws IOException {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/Basic.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
assertFileContains(path, "\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"");
// verify request name (from summary)
assertFileContains(path, "\"name\": \"Get User\"");
}
@Test
public void testBasicGenerationJson() throws IOException {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/BasicJson.json")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
assertFileContains(path, "\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"");
}
@Test
public void testValidatePostmanJson() throws IOException {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
files.forEach(File::deleteOnExit);
final ObjectMapper mapper = new ObjectMapper();
mapper.readTree(new File(output + "/postman.json"));
}
@Test
public void testVariables() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
files.forEach(File::deleteOnExit);
assertFileExists(Paths.get(output + "/postman.json"));
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(new File(output + "/postman.json"));
// verify json has variables
assertTrue(jsonNode.get("variable") instanceof ArrayNode);
assertEquals(5, ((ArrayNode) jsonNode.get("variable")).size());
}
@Test
public void testVariablesInRequestExample() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/BasicVariablesInExample.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(new File(output + "/postman.json"));
// verify json has variables
assertTrue(jsonNode.get("variable") instanceof ArrayNode);
assertEquals(4, ((ArrayNode) jsonNode.get("variable")).size());
assertFileContains(path, "{{MY_VAR_NAME}}");
}
@Test
public void testSkipPostmanVariables() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.addAdditionalProperty(PostmanCollectionCodegen.POSTMAN_VARIABLES, false)
.setInputSpec("src/test/resources/3_0/postman-collection/BasicVariablesInExample.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(new File(output + "/postman.json"));
// verify json has variables
assertTrue(jsonNode.get("variable") instanceof ArrayNode);
assertEquals(2, ((ArrayNode) jsonNode.get("variable")).size());
}
@Test
public void testGenerateWithoutPathParamsVariables() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.addAdditionalProperty(PostmanCollectionCodegen.PATH_PARAMS_AS_VARIABLES, false)
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
assertFileExists(Paths.get(output + "/postman.json"));
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(new File(output + "/postman.json"));
// verify json has variables
assertTrue(jsonNode.get("variable") instanceof ArrayNode);
assertEquals(4, ((ArrayNode) jsonNode.get("variable")).size());
}
@Test
public void testComponentExamples() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
// verify response body comes from components/examples
assertFileContains(path, "\"name\": \"Example request for Get User\"");
assertFileContains(path, "\"raw\": \"{\\n \\\"id\\\" : 777,\\n \\\"firstName\\\" : \\\"Alotta\\\",\\n \\\"lastName\\\" : \\\"Rotta\\\",\\n ");
}
@Test
public void testNamingRequestsWithUrl() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
// verify request name (from path)
assertFileContains(path, "\"name\": \"/users/{{userId}}\"");
}
@Test
public void testExampleFromSchema() throws IOException, Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.addAdditionalProperty(PostmanCollectionCodegen.REQUEST_PARAMETER_GENERATION, "Schema")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
// verify request name (from path)
assertFileContains(path, "{\\n \\\"firstName\\\": \\\"<string>\\\",\\n \\\"lastName\\\": \\\"<string>\\\",\\n \\\"email\\\": \\\"<string>\\\",\\n \\\"dateOfBirth\\\": \\\"<date>\\\"\\n}");
}
@Test
public void testSecuritySchemes() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
// check auth basic (1st security scheme in OpenAPI file)
assertFileContains(path, "\"auth\": { \"type\": \"basic\", \"basic\": [");
// check auth apiKey NOT found
assertFileNotContains(path, "\"auth\": { \"type\": \"apikey\", \"apikey\": [");
}
@Test
public void doubleCurlyBraces() {
String str = "/api/{var}/archive";
assertEquals("/api/{{var}}/archive", new PostmanCollectionCodegen().doubleCurlyBraces(str));
}
@Test
public void doubleCurlyBracesNoChanges() {
String str = "/api/{{var}}/archive";
assertEquals("/api/{{var}}/archive", new PostmanCollectionCodegen().doubleCurlyBraces(str));
}
@Test
public void extractExampleByName() {
String str = "#/components/examples/get-user-basic";
assertEquals("get-user-basic", new PostmanCollectionCodegen().extractExampleByName(str));
}
@Test
public void mapToPostmanType() {
assertEquals("string", new PostmanCollectionCodegen().mapToPostmanType("String"));
assertEquals("number", new PostmanCollectionCodegen().mapToPostmanType("integer"));
assertEquals("any", new PostmanCollectionCodegen().mapToPostmanType("object"));
}
@Test
public void testJsonExampleIncludingValueWithCommas() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/JsonWithCommasInJsonExample.json")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
// check value with commas within quotes
assertFileContains(path, "\\\"acceptHeader\\\" : \\\"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\\\"");
}
@Test
public void testDeprecatedEndpoint() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/SampleProject.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(configurator.toClientOptInput()).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
// verify request name (from path)
assertFileContains(path, "(DEPRECATED)");
}
@Test
public void testGeneratedVariables() throws Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.setInputSpec("src/test/resources/3_0/postman-collection/BasicVariablesInExample.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
assertFileContains(path, "\\\"createDate\\\" : \\\"{{$guid}}\\\"");
assertFileContains(path, "\\\"dateOfBirth\\\" : \\\"{{$isoTimestamp}}\\\"");
}
@Test
public void testSkipGeneratedVariables() throws IOException, Exception {
File output = Files.createTempDirectory("postmantest_").toFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("postman-collection")
.addAdditionalProperty(PostmanCollectionCodegen.POSTMAN_GUID, false)
.addAdditionalProperty(PostmanCollectionCodegen.POSTMAN_ISO_TIMESTAMP, false)
.setInputSpec("src/test/resources/3_0/postman-collection/BasicVariablesInExample.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
DefaultGenerator generator = new DefaultGenerator();
List<File> files = generator.opts(clientOptInput).generate();
System.out.println(files);
files.forEach(File::deleteOnExit);
Path path = Paths.get(output + "/postman.json");
assertFileExists(path);
assertFileNotContains(path, "\\\"createDate\\\" : \\\"{{$guid}}\\\"");
assertFileNotContains(path, "\\\"dateOfBirth\\\" : \\\"{{$isoTimestamp}}\\\"");
}
@Test
public void testFormatDescription() {
final String DESCRIPTION = "## Description \n\n Text with markdown \n";
final String EXPECTED = "## Description \\n\\n Text with markdown \\n";
assertEquals(EXPECTED, new PostmanCollectionCodegen().formatDescription(DESCRIPTION));
}
@Test
public void testExtractPlaceholders() {
final String INPUT = "Input with {{placeholder_1}} and {{placeholder_2}}";
assertEquals(2, new PostmanCollectionCodegen().extractPlaceholders(INPUT).size());
}
@Test
public void testExtractWithDuplicatePlaceholders() {
final String INPUT = "Input with {{placeholder_1}}, {{placeholder_2}} and again {{placeholder_2}}";
assertEquals(2, new PostmanCollectionCodegen().extractPlaceholders(INPUT).size());
}
@Test
public void testExtractPlaceholdersIncludingGuidFormula() {
final String INPUT = "Input with {{placeholder_1}} and {{$guid}}";
assertEquals(1, new PostmanCollectionCodegen().extractPlaceholders(INPUT).size());
}
@Test
public void testIsPostmanDynamicVariable() {
assertTrue(new PostmanCollectionCodegen().isPostmanDynamicVariable("$guid"));
}
// test helpers
@Test
public void getPostmanTypeNumber() {
CodegenProperty codegenProperty = new CodegenProperty();
codegenProperty.isNumeric = true;
assertEquals("number", new PostmanCollectionCodegen().getPostmanType(codegenProperty));
}
@Test
public void getPostmanTypeDate() {
CodegenProperty codegenProperty = new CodegenProperty();
codegenProperty.isDate = true;
assertEquals("date", new PostmanCollectionCodegen().getPostmanType(codegenProperty));
}
@Test
public void getPostmanTypeString() {
CodegenProperty codegenProperty = new CodegenProperty();
codegenProperty.isString = true;
assertEquals("string", new PostmanCollectionCodegen().getPostmanType(codegenProperty));
}
@Test
public void getExampleFromSchema() {
final String EXPECTED = "{\\n \\\"firstname\\\": \\\"<string>\\\",\\n \\\"lastname\\\": \\\"<string>\\\",\\n \\\"age\\\": \\\"<number>\\\",\\n \\\"birthDate\\\": \\\"<date>\\\"\\n}";
CodegenParameter codegenParameter = new CodegenParameter();
codegenParameter.vars.add(new CodegenProperty() {{
baseName = "firstname";
isString = true;
}});
codegenParameter.vars.add(new CodegenProperty() {{
baseName = "lastname";
isString = true;
}});
codegenParameter.vars.add(new CodegenProperty() {{
baseName = "age";
isNumeric = true;
}});
codegenParameter.vars.add(new CodegenProperty() {{
baseName = "birthDate";
isDate = true;
}});
assertEquals(EXPECTED, new PostmanCollectionCodegen().getJsonFromSchema(codegenParameter));
}
@Test
public void formatJson() {
final String EXPECTED = "{\\n \\\"id\\\" : 1,\\n \\\"city\\\" : \\\"Amsterdam\\\"\\n}";
final String JSON = "{\"id\":1,\"city\":\"Amsterdam\"}";
assertEquals(EXPECTED, new PostmanCollectionCodegen().formatJson(JSON));
}
@Test
public void formatJsonIncludingCommas() {
final String EXPECTED = "{\\n \\\"id\\\" : 1,\\n \\\"list\\\" : \\\"AMS,LON,ROM\\\"\\n}";
final String JSON = "{\"id\":1,\"list\":\"AMS,LON,ROM\"}";
assertEquals(EXPECTED, new PostmanCollectionCodegen().formatJson(JSON));
}
@Test
public void getAttributesFromJson() {
final String JSON = "{\"id\":1,\"list\":\"AMS,LON,ROM\"}";
assertEquals(2, new PostmanCollectionCodegen().getAttributes(JSON).length);
}
@Test
public void convertObjectNodeToJson() {
final String EXPECTED = "{\\n \\\"id\\\" : 1,\\n \\\"city\\\" : \\\"Amsterdam\\\"\\n}";
ObjectMapper mapper = new ObjectMapper();
ObjectNode city = mapper.createObjectNode();
city.put("id", 1);
city.put("city", "Amsterdam");
assertEquals(EXPECTED, new PostmanCollectionCodegen().convertToJson(city));
}
@Test
public void convertObjectNodeIncludingDoubleQuoteToJson() {
final String EXPECTED = "{\\n \\\"id\\\" : 1,\\n \\\"city\\\" : \\\"it is \\\\\"Amsterdam\\\\\" \\\"\\n}";
ObjectMapper mapper = new ObjectMapper();
ObjectNode city = mapper.createObjectNode();
city.put("id", 1);
city.put("city", "it is \"Amsterdam\" ");
assertEquals(EXPECTED, new PostmanCollectionCodegen().convertToJson(city));
}
@Test
public void convertLinkedHashMapToJson() {
final String EXPECTED = "{\\n \\\"id\\\": 1,\\n \\\"city\\\": \\\"Amsterdam\\\"\\n}";
LinkedHashMap<String, Object> city = new LinkedHashMap<>();
city.put("id", 1);
city.put("city", "Amsterdam");
assertEquals(EXPECTED, new PostmanCollectionCodegen().convertToJson(city));
}
@Test
public void convertNestedLinkedHashMapToJson() {
final String EXPECTED =
"{\\n " +
"\\\"id\\\": 1,\\n \\\"city\\\": \\\"Amsterdam\\\",\\n " +
"\\\"country\\\": {\\n \\\"id\\\": 2,\\n \\\"code\\\": \\\"NL\\\"\\n}" +
"\\n}";
LinkedHashMap<String, Object> city = new LinkedHashMap<>();
city.put("id", 1);
city.put("city", "Amsterdam");
LinkedHashMap<String, Object> country = new LinkedHashMap<>();
country.put("id", 2);
country.put("code", "NL");
city.put("country", country);
assertEquals(EXPECTED, new PostmanCollectionCodegen().convertToJson(city));
}
}

View File

@ -0,0 +1,106 @@
openapi: 3.0.0
info:
title: Basic
version: '1.0'
description: Sample API
license:
name: Apache 2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0'
servers:
- url: 'http://localhost:5001'
description: dev server
- url: 'http://localhost:5001'
description: test server
paths:
'/users/{userId}':
get:
summary: Get User
description: Get User Info by User ID
operationId: get-users-userId
tags:
- basic
parameters:
- description: Unique identifier of the user
name: userId
in: path
required: true
schema:
type: string
responses:
'200':
description: User Found
content:
application/json:
schema:
$ref: '#/components/schemas/User'
examples:
Get User Alice Smith (json):
value:
id: 142
firstName: Alice
lastName: Smith
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
signUpDate: '2019-08-24'
application/xml:
schema:
$ref: '#/components/schemas/User'
examples:
Get User Alice Smith (xml):
value:
id: 143
firstName: Alice
lastName: Smith
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
signUpDate: '2019-08-24'
'404':
description: User Not Found
components:
schemas:
User:
title: User
type: object
description: ''
x-examples:
Alice Smith:
id: 144
firstName: Alice
lastName: Smith
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
signUpDate: '2019-08-24'
properties:
id:
type: integer
description: Unique identifier for the given user.
firstName:
type: string
lastName:
type: string
email:
type: string
format: email
dateOfBirth:
type: string
format: date
example: '1997-10-31'
emailVerified:
type: boolean
description: Set to true if the user's email has been verified.
createDate:
type: string
format: date
description: The date that the user was created.
required:
- id
- firstName
- lastName
- email
- emailVerified
tags:
- name: basic
description: Basic tag

View File

@ -0,0 +1,167 @@
{
"openapi" : "3.0.0",
"info" : {
"description" : "Sample API",
"license" : {
"name" : "Apache 2.0",
"url" : "https://www.apache.org/licenses/LICENSE-2.0"
},
"title" : "Basic",
"version" : "1.0"
},
"servers" : [ {
"description" : "dev server",
"url" : "http://localhost:{port}/{version}",
"variables": {
"version": {
"default": "v1",
"description": "version of the API"
},
"port": {
"enum": [
"5000",
"8080"
],
"default": "5000"
}
}
}, {
"description" : "test server",
"url" : "http://localhost:{port}/{version}",
"variables": {
"version": {
"default": "v1",
"description": "version of the API"
},
"port": {
"enum": [
"5000",
"8080"
],
"default": "5000"
}
}
} ],
"tags" : [ {
"description" : "Basic tag",
"name" : "basic"
} ],
"paths" : {
"/users/{userId}" : {
"get" : {
"description" : "Get User Info by User ID",
"operationId" : "get-users-userId",
"parameters" : [ {
"description" : "Unique identifier of the user",
"explode" : false,
"in" : "path",
"name" : "userId",
"required" : true,
"schema" : {
"type" : "string"
},
"style" : "simple"
} ],
"responses" : {
"200" : {
"content" : {
"application/json" : {
"examples" : {
"Get User Alice Smith (json)" : {
"value" : {
"id" : 142,
"firstName" : "Alice",
"lastName" : "Smith",
"email" : "alice.smith@gmail.com",
"dateOfBirth" : "1997-10-31",
"emailVerified" : true,
"signUpDate" : "2019-08-24"
}
}
},
"schema" : {
"$ref" : "#/components/schemas/User"
}
},
"application/xml" : {
"examples" : {
"Get User Alice Smith (xml)" : {
"value" : {
"id" : 143,
"firstName" : "Alice",
"lastName" : "Smith",
"email" : "alice.smith@gmail.com",
"dateOfBirth" : "1997-10-31",
"emailVerified" : true,
"signUpDate" : "2019-08-24"
}
}
},
"schema" : {
"$ref" : "#/components/schemas/User"
}
}
},
"description" : "User Found"
},
"404" : {
"description" : "User Not Found"
}
},
"summary" : "Get User",
"tags" : [ "basic" ]
}
}
},
"components" : {
"schemas" : {
"User" : {
"description" : "",
"properties" : {
"id" : {
"description" : "Unique identifier for the given user.",
"type" : "integer"
},
"firstName" : {
"type" : "string"
},
"lastName" : {
"type" : "string"
},
"email" : {
"format" : "email",
"type" : "string"
},
"dateOfBirth" : {
"example" : "1997-10-31",
"format" : "date",
"type" : "string"
},
"emailVerified" : {
"description" : "Set to true if the user's email has been verified.",
"type" : "boolean"
},
"createDate" : {
"description" : "The date that the user was created.",
"format" : "date",
"type" : "string"
}
},
"required" : [ "email", "emailVerified", "firstName", "id", "lastName" ],
"title" : "User",
"type" : "object",
"x-examples" : {
"Alice Smith" : {
"id" : 144,
"firstName" : "Alice",
"lastName" : "Smith",
"email" : "alice.smith@gmail.com",
"dateOfBirth" : "1997-10-31",
"emailVerified" : true,
"signUpDate" : "2019-08-24"
}
}
}
}
}
}

View File

@ -0,0 +1,116 @@
openapi: 3.0.0
info:
title: BasicExample
version: '1.0'
description: Sample API
license:
name: Apache 2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0'
servers:
- url: 'http://localhost:5001'
description: dev server
- url: 'http://localhost:5001'
description: test server
paths:
'/users/{userId}':
patch:
summary: Patch User
description: Update User Info
operationId: patch-users-userId
tags:
- basic
parameters:
- description: Unique identifier of the user
name: userId
in: path
required: true
schema:
type: string
requestBody:
content:
application/json:
examples:
patch-user:
$ref: '#/components/examples/patch-user-example'
schema:
$ref: '#/components/schemas/User'
responses:
'200':
description: User Found
content:
application/json:
schema:
$ref: '#/components/schemas/User'
examples:
Get User Alice Smith (json):
value:
id: 142
firstName: Alice
lastName: Smith
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
signUpDate: '2019-08-24'
application/xml:
schema:
$ref: '#/components/schemas/User'
examples:
Get User Alice Smith (xml):
value:
id: 143
firstName: Alice
lastName: Smith
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
signUpDate: '2019-08-24'
'404':
description: User Not Found
components:
schemas:
User:
title: User
type: object
description: ''
properties:
id:
type: integer
description: Unique identifier for the given user.
firstName:
type: string
lastName:
type: string
email:
type: string
format: email
dateOfBirth:
type: string
format: date
emailVerified:
type: boolean
description: Set to true if the user's email has been verified.
createDate:
type: string
format: date
description: The date that the user was created.
required:
- id
- firstName
- lastName
- email
- emailVerified
examples:
patch-user-example:
summary: Example patch user
value:
id: 001
firstName: "{{MY_VAR_NAME}}"
lastName: "{{MY_VAR_LAST_NAME}}"
email: alotta.rotta@gmail.com
dateOfBirth: "{{ISO_TIMESTAMP}}"
emailVerified: true
createDate: "{{UNIQUE_REFERENCE}}"
tags:
- name: basic
description: Basic tag

View File

@ -0,0 +1,75 @@
{
"openapi" : "3.0.0",
"info" : {
"description" : "Sample API",
"title" : "Basic",
"version" : "1.0"
},
"tags" : [ {
"description" : "Basic tag",
"name" : "basic"
} ],
"paths" : {
"/ws" : {
"post" : {
"description" : "Create",
"operationId" : "ws-post",
"requestBody" : {
"content" : {
"application/json" : {
"examples" : {
"basic" : {
"$ref" : "#/components/examples/ex-1"
}
},
"schema" : {
"$ref" : "#/components/schemas/Item"
}
}
}
},
"responses" : {
"200" : {
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/Item"
}
}
},
"description" : "Item created"
}
},
"summary" : "Create",
"tags" : [ "basic" ]
}
}
},
"components" : {
"schemas" : {
"Item" : {
"description" : "",
"properties" : {
"id" : {
"description" : "Item id",
"type" : "integer"
},
"acceptHeader" : {
"type" : "string"
}
},
"title" : "item",
"type" : "object"
}
},
"examples": {
"ex-1": {
"summary" : "Example 1",
"value" : {
"id": 1,
"acceptHeader": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
}
}
}
}
}

View File

@ -0,0 +1,310 @@
openapi: 3.0.0
info:
title: Sample project
version: '1.0'
description: 'Sample API Check "API Key" '
license:
name: Apache 2.0
url: 'https://www.apache.org/licenses/LICENSE-2.0'
servers:
- url: 'http://localhost:{port}/{version}'
description: dev server
variables:
port:
description: Port number
enum:
- '5000'
- '8080'
default: '5000'
version:
default: v1
description: API version
- url: 'http://localhost:{port}/{version}'
description: test server
variables:
port:
description: Port number
enum:
- '5000'
- '8080'
default: '5000'
version:
default: v1
description: API version
paths:
'/users/':
get:
summary: Get User Info by Query Param
operationId: get-users-query-id
description: Retrieve the information of the user with the matching user ID.
tags:
- basic
parameters:
- description: Query Id.
name: pUserId
in: query
required: true
schema:
type: string
example: 888
responses:
'200':
description: User Found
content:
application/json:
schema:
$ref: '#/components/schemas/User'
example:
id: schema-example
firstName: Alice
lastName: Smith333
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
signUpDate: '2019-08-24'
examples:
Get User Alice Smith:
value:
id: 142
firstName: Alice
lastName: Smith
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
signUpDate: '2019-08-24'
Get User Phil Smith:
value:
id: 143
firstName: Phil
lastName: Smith
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
signUpDate: '2019-08-24'
'404':
description: User Not Found
'/users/{userId}':
parameters:
- schema:
type: integer
examples:
a:
value: a
summary: a summary
b:
value: b
summary: b summary
name: userId
in: path
required: true
description: Id of an existing user.
- schema:
type: string
default: code_one
name: strCode
in: header
description: Code as header
- schema:
type: string
name: strCode2
in: header
description: Code as header2
get:
summary: Get User Info by User ID
tags:
- advanced
responses:
'200':
description: User Found
content:
application/json:
schema:
$ref: '#/components/schemas/User'
example:
id: 9998
firstName: Alice9998 resp example
lastName: Smith9998
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
createDate: '2019-08-24'
'404':
description: User Not Found
operationId: get-users-userId
description: Retrieve the information of the user with the matching user ID.
patch:
summary: Update User Information
deprecated: true
operationId: patch-users-userId
responses:
'200':
description: User Updated
content:
application/json:
schema:
$ref: '#/components/schemas/User'
examples:
Updated User Rebecca Baker:
value:
id: 13
firstName: Rebecca
lastName: Baker
email: rebecca@gmail.com
dateOfBirth: '1985-10-02'
emailVerified: false
createDate: '2019-08-24'
'404':
description: User Not Found
'409':
description: Email Already Taken
description: Update the information of an existing user.
requestBody:
content:
application/json:
schema:
type: object
properties:
firstName:
type: string
lastName:
type: string
email:
type: string
description: >-
If a new email is given, the user's email verified property
will be set to false.
dateOfBirth:
type: string
examples:
Update First Name:
value:
firstName: Rebecca
Update Email:
value:
email: rebecca@gmail.com
Update Last Name & Date of Birth:
value:
lastName: Baker
dateOfBirth: '1985-10-02'
description: Patch user properties to update.
/user:
post:
summary: Create New User
operationId: post-user
responses:
'200':
description: User Created
content:
application/json:
schema:
$ref: '#/components/schemas/User'
examples:
basic:
$ref: '#/components/examples/get-user-basic'
'400':
description: Missing Required Information
'409':
description: Email Already Taken
requestBody:
content:
application/json:
schema:
type: object
properties:
firstName:
type: string
lastName:
type: string
email:
type: string
dateOfBirth:
type: string
format: date
required:
- firstName
- lastName
- email
- dateOfBirth
examples:
basic:
$ref: '#/components/examples/get-user-basic'
description: Post the necessary fields for the API to create a new user.
description: Create a new user.
tags:
- basic
components:
securitySchemes:
BasicAuth:
type: http
scheme: basic
BearerAuth:
type: http
scheme: bearer
ApiKeyAuth:
type: apiKey
name: X-API-Key
in: header
schemas:
User:
title: User
type: object
description: ''
example:
id: 999
firstName: Alice9 schema example
lastName: Smith9
email: alice.smith@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
createDate: '2019-08-24'
properties:
id:
type: integer
description: Unique identifier for the given user.
example: 0
firstName:
type: string
example: Alix
lastName:
type: string
example: Smith
email:
type: string
format: email
example: alix.smith@gmail.com
dateOfBirth:
type: string
format: date
example: '1997-10-31'
emailVerified:
type: boolean
description: Set to true if the user's email has been verified.
example: true
createDate:
type: string
format: date
description: The date that the user was created.
example: '2019-08-24'
required:
- id
- firstName
- lastName
- email
- emailVerified
examples:
get-user-basic:
summary: Example request for Get User
value:
id: 777
firstName: Alotta
lastName: Rotta
email: alotta.rotta@gmail.com
dateOfBirth: '1997-10-31'
emailVerified: true
createDate: '2019-08-24'
tags:
- name: basic
description: Basic tag
- name: advanced
description: Advanced tag

View File

@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1 @@
postman.json

View File

@ -0,0 +1 @@
6.6.0-SNAPSHOT

View File

@ -0,0 +1,275 @@
{
"info": {
"name": "Sample project",
"description": {
"content": "Sample API Check \"API Key\" ",
"type": "text/markdown"
},
"version": "1.0",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "default",
"item": [
{
"name": "/users/{{userId}} (DEPRECATED)",
"description": "Update the information of an existing user.",
"item": [
{
"name": "Update User Information",
"request": {
"method": "PATCH",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Accept",
"value": "application/json"
},
{
"key": "strCode",
"value": "code_one"
},
{
"key": "strCode2",
"value": "null"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"firstName\" : \"Rebecca\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/users/{{userId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"users",
"{{userId}}"
],
"variable": [
{
"key": "userId",
"value": "",
"description": "Id of an existing user."
}
],
"query": [
]
},
"description": "Update the information of an existing user."
}
}
]
}
]
},
{
"name": "advanced",
"item": [
{
"name": "/users/{{userId}}",
"description": "Retrieve the information of the user with the matching user ID.",
"item": [
{
"name": "Get User Info by User ID",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
},
{
"key": "strCode",
"value": "code_one"
},
{
"key": "strCode2",
"value": "null"
}
],
"body": {
"mode": "raw",
"raw": "",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/users/{{userId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"users",
"{{userId}}"
],
"variable": [
{
"key": "userId",
"value": "",
"description": "Id of an existing user."
}
],
"query": [
]
},
"description": "Retrieve the information of the user with the matching user ID."
}
}
]
}
]
},
{
"name": "basic",
"item": [
{
"name": "/users/",
"description": "Retrieve the information of the user with the matching user ID.",
"item": [
{
"name": "Get User Info by Query Param",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/users/",
"host": [
"{{baseUrl}}"
],
"path": [
"users"
],
"variable": [
],
"query": [
{
"key": "pUserId",
"value": "888"
}
]
},
"description": "Retrieve the information of the user with the matching user ID."
}
}
]
},
{
"name": "/user",
"description": "Create a new user.",
"item": [
{
"name": "Example request for Get User",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Accept",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"id\" : 777,\n \"firstName\" : \"Alotta\",\n \"lastName\" : \"Rotta\",\n \"email\" : \"alotta.rotta@gmail.com\",\n \"dateOfBirth\" : \"1997-10-31\",\n \"emailVerified\" : true,\n \"createDate\" : \"2019-08-24\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/user",
"host": [
"{{baseUrl}}"
],
"path": [
"user"
],
"variable": [
],
"query": [
]
},
"description": "Create a new user."
}
}
]
}
]
}
],
"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "{{USERNAME}}",
"type": "string"
},
{
"key": "password",
"value": "{{PASSWORD}}",
"type": "string"
}
]
},
"variable": [
{
"key": "baseUrl",
"value": "http://localhost:{port}/{version}",
"type": "string"
},
{
"key": "X-API-Key",
"value": "",
"type": "string"
},
{
"key": "version",
"value": "v1",
"type": "string"
},
{
"key": "port",
"value": "5000",
"type": "string"
},
{
"key": "userId",
"value": "a",
"type": "number"
}
]
}

View File

@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1 @@
postman.json

View File

@ -0,0 +1 @@
7.0.0-SNAPSHOT

View File

@ -0,0 +1,275 @@
{
"info": {
"name": "Sample project",
"description": {
"content": "Sample API Check \"API Key\" ",
"type": "text/markdown"
},
"version": "1.0",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "default",
"item": [
{
"name": "/users/{{userId}} (DEPRECATED)",
"description": "Update the information of an existing user.",
"item": [
{
"name": "Update User Information",
"request": {
"method": "PATCH",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Accept",
"value": "application/json"
},
{
"key": "strCode",
"value": "code_one"
},
{
"key": "strCode2",
"value": "null"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"firstName\" : \"Rebecca\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/users/{{userId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"users",
"{{userId}}"
],
"variable": [
{
"key": "userId",
"value": "",
"description": "Id of an existing user."
}
],
"query": [
]
},
"description": "Update the information of an existing user."
}
}
]
}
]
},
{
"name": "advanced",
"item": [
{
"name": "/users/{{userId}}",
"description": "Retrieve the information of the user with the matching user ID.",
"item": [
{
"name": "Get User Info by User ID",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
},
{
"key": "strCode",
"value": "code_one"
},
{
"key": "strCode2",
"value": "null"
}
],
"body": {
"mode": "raw",
"raw": "",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/users/{{userId}}",
"host": [
"{{baseUrl}}"
],
"path": [
"users",
"{{userId}}"
],
"variable": [
{
"key": "userId",
"value": "",
"description": "Id of an existing user."
}
],
"query": [
]
},
"description": "Retrieve the information of the user with the matching user ID."
}
}
]
}
]
},
{
"name": "basic",
"item": [
{
"name": "/users/",
"description": "Retrieve the information of the user with the matching user ID.",
"item": [
{
"name": "Get User Info by Query Param",
"request": {
"method": "GET",
"header": [
{
"key": "Accept",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/users/",
"host": [
"{{baseUrl}}"
],
"path": [
"users"
],
"variable": [
],
"query": [
{
"key": "pUserId",
"value": "888"
}
]
},
"description": "Retrieve the information of the user with the matching user ID."
}
}
]
},
{
"name": "/user",
"description": "Create a new user.",
"item": [
{
"name": "Example request for Get User",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
},
{
"key": "Accept",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": "{\n \"id\" : 777,\n \"firstName\" : \"Alotta\",\n \"lastName\" : \"Rotta\",\n \"email\" : \"alotta.rotta@gmail.com\",\n \"dateOfBirth\" : \"1997-10-31\",\n \"emailVerified\" : true,\n \"createDate\" : \"2019-08-24\"\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/user",
"host": [
"{{baseUrl}}"
],
"path": [
"user"
],
"variable": [
],
"query": [
]
},
"description": "Create a new user."
}
}
]
}
]
}
],
"auth": {
"type": "basic",
"basic": [
{
"key": "username",
"value": "{{USERNAME}}",
"type": "string"
},
{
"key": "password",
"value": "{{PASSWORD}}",
"type": "string"
}
]
},
"variable": [
{
"key": "baseUrl",
"value": "http://localhost:{port}/{version}",
"type": "string"
},
{
"key": "X-API-Key",
"value": "",
"type": "string"
},
{
"key": "version",
"value": "v1",
"type": "string"
},
{
"key": "port",
"value": "5000",
"type": "string"
},
{
"key": "userId",
"value": "a",
"type": "number"
}
]
}