Skip to content

Instantly share code, notes, and snippets.

@sreesarma
Last active September 19, 2022 06:57
Show Gist options
  • Select an option

  • Save sreesarma/b72cabcc3a6293a95466c89299df416a to your computer and use it in GitHub Desktop.

Select an option

Save sreesarma/b72cabcc3a6293a95466c89299df416a to your computer and use it in GitHub Desktop.
Generate Wiki-formatted API Documentation from Postman Collections
# 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