Last active
September 19, 2022 06:57
-
-
Save sreesarma/b72cabcc3a6293a95466c89299df416a to your computer and use it in GitHub Desktop.
Generate Wiki-formatted API Documentation from Postman Collections
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # See "Postman to Wiki" at https://medium.com/@sreedharc/postman-to-wiki-e7d31c76db57 for more information | |
| # Generates Markdown for Confluence Wiki from a given Collection file exported from Postman per Collections 2.1 schema | |
| # Change working_dir and input_file to suit, then run it | |
| import json | |
| from operator import itemgetter | |
| from itertools import groupby | |
| # A postman collection, in Postman 2.1 format | |
| working_dir = "$FOLDER_PATH" | |
| input_file = working_dir + "\$EXPORTED_COLLECTION.json" | |
| serial_num = 1 | |
| def clean(s): | |
| s = (str(s).decode('string_escape')) | |
| s = s.replace('{{', '$').replace('}}', '').replace('\r\n', '') | |
| return s[1:-1] | |
| def clean_list(a_list): | |
| return [clean(i) for i in str(a_list).split(',')] | |
| # Generates markdown for the section describing Collection Variables | |
| def gen_variables_section(list_of_variables): | |
| op = "h2.Variables Used in this Collection" + "\n" | |
| op += "||Name||Description||Example||" + "\n" | |
| for variable in sorted(list_of_variables, key=itemgetter('key')): | |
| op += "|" + variable["key"] + "| |" + variable["value"] + "|" + "\n" | |
| return op | |
| # Generates markdown for request section | |
| def gen_request_section(item): | |
| item = json.loads(json.dumps(item)) | |
| # Heading, e.g. GET Users | |
| request_section = "h2." + "{color:#3ebb3e}" + item["request"]["method"] + "{color} " + item["name"] + "\n" | |
| # Description | |
| if "description" in item["request"]: | |
| request_section += item["request"]["description"] + "\n" | |
| request_section += "\nh3. Request" + "\n" | |
| # URL format | |
| request_section += "h4. Request URL" + "\n" | |
| request_section += "{panel}" | |
| request_section += "* *{color:red}Production Instance{color}:* " + item["request"]["url"]["raw"].replace("{{", "$").replace("}}", "") + "\n" | |
| request_section += "* *Staging Instance:* " + item["request"]["url"]["raw"].replace("nmvip", "nmvip-staging").replace("{{", "$").replace("}}", "") + "\n" | |
| request_section += "{panel}" + "\n" | |
| # Headers | |
| # print("# Headers: " + len(item["request"]["header"])) | |
| request_section += "h4. Request Headers" + "\n" | |
| request_section += "||Key||Value||Description||" + "\n" | |
| for header in item["request"]["header"]: | |
| request_section += "|" + header["key"] + "|" + header["value"] | |
| description = " " | |
| if "description" in header: | |
| description = header["description"] | |
| request_section += "|" + description + "|" + "\n" | |
| # Request Parameters | |
| add_param_section = False | |
| param_section = "\nh4. Request Parameters" + "\n" | |
| param_section += "||Parameter Type||Key||Value||Description||" + "\n" | |
| url = item["request"]["url"] | |
| # Path Parameters | |
| if "path" in url: | |
| path_parameters = url["path"] | |
| for param in path_parameters: | |
| ps = param.decode() | |
| if "{{" in param: | |
| add_param_section = True | |
| param_section += "|" + "Path Parameter" + "|" + param.replace("{{", "$").replace("}}", "") \ | |
| + "|" + " " + "|" + " " + "|" + "\n" | |
| # Query String Parameters | |
| if "query" in url: | |
| qs_parameters = url["query"] | |
| for param in qs_parameters: | |
| add_param_section = True | |
| param_section += "|" + "Query String Parameter" + "|" + param["key"] \ | |
| + "|" + param["value"] + "|" + " " + "|" + "\n" | |
| print(param_section) | |
| if add_param_section: | |
| print("ADD PARAMETERS SECTION") | |
| request_section += param_section | |
| # Request payload as code snippet | |
| if str(item["request"]["method"]) != "GET": | |
| request_section += "\nh4. Request Payload" + "\n" | |
| payload = "{code:title=" + "Payload" \ | |
| + "|theme=FadeToGrey|linenumbers=true|language=javascript|firstline=0001|collapse=true}" | |
| # print(item["request"]["body"]) | |
| if item["request"]["body"] is None: | |
| # print("No Payload") | |
| payload += "{}" | |
| else: | |
| p = json.dumps(item["request"]["body"]) | |
| # print("CLEANED UP") | |
| if "raw" in item["request"]["body"]: | |
| x = clean(json.dumps(json.loads(p)["raw"])) | |
| # print(x) | |
| payload += json.dumps(json.loads(x, 'ascii'), indent=2) | |
| else: | |
| payload += "{}" | |
| payload += "{code}" | |
| # print("PAYLOAD: \n" + payload) | |
| request_section += payload | |
| payload = "" | |
| else: | |
| print("Danger!! ") | |
| return request_section | |
| # Generates markdown for response section | |
| def gen_response_section(item): | |
| item = json.loads(json.dumps(item)) | |
| response = json.loads(json.dumps(item["response"])) | |
| response_section = "\nh3. Response " + "\n" | |
| # print(item["name"] + " - " + str(len(response))) | |
| if len(response) > 0: | |
| code = "200*" | |
| if "code" in response[0]: | |
| code = str(response[0]["code"]) | |
| else: | |
| print(response[0]) | |
| status = "OK*" | |
| if "status" in response[0]: | |
| status = str(response[0]["status"]) | |
| else: | |
| print(response[0]) | |
| # Response body as code snippet, response code + status as snippet title | |
| response_section += "{code:title=" + code + " " + status \ | |
| + "|theme=FadeToGrey|linenumbers=true|language=javascript|firstline=0001|collapse=true}" | |
| body = " " | |
| if "body" in response[0]: | |
| body = response[0]["body"] | |
| if response[0]["body"] is None: | |
| body = "{}" | |
| # print("BODY: \n" + body) | |
| body = json.dumps(json.loads(body, 'ascii'), indent=2) | |
| else: | |
| print("Danger!! ") | |
| response_section += body | |
| response_section += "{code}" | |
| return response_section | |
| # Generates a section for the given resource | |
| def gen_resource_section(name, group): | |
| global serial_num | |
| global working_dir | |
| resource_section = "\n" | |
| for item in group: | |
| print("\t Processing " + str(item["request"]["method"])) | |
| resource_section += gen_request_section(item) | |
| resource_section += gen_response_section(item) | |
| # Write to a separate output file | |
| file_name = str(serial_num) + "." + name + "-" + str(item["request"]["method"]) + ".txt" | |
| with open(working_dir + "\\generated\\" + file_name, 'w') as output_file: | |
| output_file.write(resource_section) | |
| serial_num = serial_num + 1 | |
| # Reset this! | |
| resource_section = "\n" | |
| # Read in the input as JSON | |
| with open(input_file) as json_data: | |
| input_data = json.load(json_data) | |
| # Extract all variables and print them out as a table | |
| v = gen_variables_section(input_data["variable"]) | |
| # print(v) | |
| # Now extract all requests ("items" in the collection) sorted by resource name ("name" in the collection)... | |
| items = sorted(input_data["item"], key=lambda x: (x['name'], x['request']['method'])) | |
| # print("Number of items: " + str(len(items))) | |
| # ... and generate documentation for supported methods by resource, in alphabetical order (GET, PATCH, POST, etc.) | |
| for name, group in groupby(items, key=lambda y: (y['name'])): | |
| print("Exporting: " + name) | |
| gen_resource_section(name, group) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment