Skip to content

Commit 21a538d

Browse files
authored
Merge pull request #4 from henrycjc/zeusttu-25-get-schemas-from-request-and-response-bodies
Zeusttu 25 get schemas from request and response bodies
2 parents 9631d8f + 5a75b38 commit 21a538d

File tree

2 files changed

+73
-4
lines changed

2 files changed

+73
-4
lines changed

openapi2jsonschema/command.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
allow_null_optional_fields,
1717
change_dict_values,
1818
append_no_duplicates,
19+
get_request_and_response_body_components_from_paths,
1920
)
2021
from openapi2jsonschema.errors import UnsupportedError
2122

@@ -51,8 +52,23 @@
5152
is_flag=True,
5253
help="Prohibits properties not in the schema (additionalProperties: false)",
5354
)
55+
@click.option(
56+
"--include-bodies",
57+
is_flag=True,
58+
help="Include request and response bodies as if they are components",
59+
)
5460
@click.argument("schema", metavar="SCHEMA_URL")
55-
def default(output, schema, prefix, stand_alone, expanded, kubernetes, no_all, strict):
61+
def default(
62+
output,
63+
schema,
64+
prefix,
65+
stand_alone,
66+
expanded,
67+
kubernetes,
68+
strict,
69+
no_all,
70+
include_bodies,
71+
):
5672
"""
5773
Converts a valid OpenAPI specification into a set of JSON Schema files
5874
"""
@@ -130,8 +146,14 @@ def default(output, schema, prefix, stand_alone, expanded, kubernetes, no_all, s
130146
components = data["components"]["schemas"]
131147

132148
generated_files = []
149+
150+
if include_bodies:
151+
components.update(
152+
get_request_and_response_body_components_from_paths(data["paths"]),
153+
)
154+
133155
for title in components:
134-
kind = title.split(".")[-1].lower()
156+
kind = title.split(".")[-1]
135157
if kubernetes:
136158
group = title.split(".")[-3].lower()
137159
api_version = title.split(".")[-2].lower()
@@ -168,8 +190,7 @@ def default(output, schema, prefix, stand_alone, expanded, kubernetes, no_all, s
168190
if (
169191
kubernetes
170192
and stand_alone
171-
and kind
172-
in [
193+
and kind.lower() in [
173194
"jsonschemaprops",
174195
"jsonschemapropsorarray",
175196
"customresourcevalidation",

openapi2jsonschema/util.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env python
22

3+
import re
4+
35

46
def iteritems(d):
57
if hasattr(dict, "iteritems"):
@@ -115,3 +117,49 @@ def append_no_duplicates(obj, key, value):
115117
obj[key] = []
116118
if value not in obj[key]:
117119
obj[key].append(value)
120+
121+
122+
def get_components_from_body_definition(body_definition, prefix=""):
123+
MIMETYPE_TO_TYPENAME_MAP = {
124+
"application/json": "json",
125+
"application/vnd.api+json": "jsonapi",
126+
}
127+
result = {}
128+
for mimetype, definition in body_definition.get("content", {}).items():
129+
type_name = MIMETYPE_TO_TYPENAME_MAP.get(
130+
mimetype,
131+
mimetype.replace("/", "_"),
132+
)
133+
if "schema" in definition:
134+
result["{:s}{:s}".format(prefix, type_name)] = definition["schema"]
135+
return result
136+
137+
138+
def get_request_and_response_body_components_from_paths(paths):
139+
components = {}
140+
for path, path_definition in paths.items():
141+
for http_method, http_method_definition in path_definition.items():
142+
name_prefix_fmt = "paths_{:s}_{:s}_{{:s}}_".format(
143+
# Paths "/" and "/root" will conflict,
144+
# no idea how to solve this elegantly.
145+
path.lstrip("/").replace("/", "_") or "root",
146+
http_method.upper(),
147+
)
148+
name_prefix_fmt = re.sub(
149+
r"\{([^:\}]+)\}",
150+
r"_\1_",
151+
name_prefix_fmt,
152+
)
153+
if "requestBody" in http_method_definition:
154+
components.update(get_components_from_body_definition(
155+
http_method_definition["requestBody"],
156+
prefix=name_prefix_fmt.format("request")
157+
))
158+
responses = http_method_definition["responses"]
159+
for response_code, response in responses.items():
160+
response_name_part = "response_{}".format(response_code)
161+
components.update(get_components_from_body_definition(
162+
response,
163+
prefix=name_prefix_fmt.format(response_name_part),
164+
))
165+
return components

0 commit comments

Comments
 (0)