diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PostmanCollectionCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PostmanCollectionCodegen.java index 2c40a4824754..124bc29b7933 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PostmanCollectionCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PostmanCollectionCodegen.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.io.JsonStringEncoder; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -332,8 +333,8 @@ public void addToMap(CodegenOperation codegenOperation) { } } - tagName = formatDescription(tagName); - tagDescription = formatDescription(tagDescription); + tagName = escapeJsonString(tagName); + tagDescription = escapeJsonString(tagDescription); PostmanRequestFolder folder = new PostmanRequestFolder(tagName, tagDescription); List list = codegenOperationsByTag.get(folder); @@ -685,6 +686,13 @@ public String formatDescription(String description) { return description; } + String escapeJsonString(String value) { + if (value == null) { + return null; + } + return new String(JsonStringEncoder.getInstance().quoteAsString(value)); + } + /** * Extract all placeholders (string delimited by curly braces ie {{PLACEHOLDER}}) from the input string * diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/postman/PostmanCollectionCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/postman/PostmanCollectionCodegenTest.java index 4ea8ef22ccdf..c0312506c251 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/postman/PostmanCollectionCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/postman/PostmanCollectionCodegenTest.java @@ -150,6 +150,38 @@ public void testTagDescriptionIsJsonEscaped() throws IOException { assertEquals("Basic \"quoted\" tag\nsecond line", basicFolder.get("description").asText()); } + @Test + public void testTagDescriptionControlCharsAreJsonEscaped() 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/TagDescriptionControlCharsEscaping.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + final ClientOptInput clientOptInput = configurator.toClientOptInput(); + DefaultGenerator generator = new DefaultGenerator(); + List files = generator.opts(clientOptInput).generate(); + + files.forEach(File::deleteOnExit); + + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode root = objectMapper.readTree(new File(output + "/postman.json")); + JsonNode folders = root.get("item"); + + JsonNode basicFolder = null; + for (JsonNode folder : folders) { + if ("basic".equals(folder.get("name").asText())) { + basicFolder = folder; + break; + } + } + + assertNotNull(basicFolder); + assertEquals("desc with \\t tab, \\b backspace, \\f formfeed, \\r carriage-return, \\n line", basicFolder.get("description").asText()); + } + @Test public void testValidatePostmanJson() throws IOException { diff --git a/modules/openapi-generator/src/test/resources/3_0/postman-collection/TagDescriptionControlCharsEscaping.yaml b/modules/openapi-generator/src/test/resources/3_0/postman-collection/TagDescriptionControlCharsEscaping.yaml new file mode 100644 index 000000000000..e6ca09962549 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/postman-collection/TagDescriptionControlCharsEscaping.yaml @@ -0,0 +1,33 @@ +openapi: 3.0.0 +info: + title: Tag Description Control Chars Escaping + version: '1.0' +servers: + - url: 'http://localhost:5001' +paths: + '/users/{userId}': + get: + summary: Get User + 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: + type: object + properties: + id: + type: integer +tags: + - name: basic + description: "desc with \\t tab, \\b backspace, \\f formfeed, \\r carriage-return, \\n line"