forked from rapid7/insightconnect-plugins
-
Notifications
You must be signed in to change notification settings - Fork 0
/
json_to_spec.py
executable file
·101 lines (80 loc) · 2.59 KB
/
json_to_spec.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/env python
import json
from past.builtins import basestring
from future.utils import iteritems
import sys
from collections import OrderedDict
from jinja2 import Template
import os
# set to true if you don't want to try to generate nested types
OBJECTS_ONLY = False
filename = sys.argv[1]
this_dir = os.path.dirname(__file__)
rel_path = "templates/template.json_to_spec.j2"
abs_path_template = os.path.join(this_dir, rel_path)
with open(filename) as data_file:
data = json.load(data_file)
with open(abs_path_template) as f:
spec_template = Template(f.read())
type_refs = {}
types = OrderedDict()
output = OrderedDict()
def type_name_unused(name):
if not name in types:
return name
i = 0
while True:
name = "%s_%d" % (name, i)
if not name in types:
return name
i += 1
def detect_type(name, value, level=0):
if isinstance(value, basestring):
return "string"
if isinstance(value, bool):
return "boolean"
if isinstance(value, int):
return "integer"
if isinstance(value, float):
return "float"
if isinstance(value, list):
if value:
return '"[]{}"'.format(detect_type(name, value[0], level + 1))
else:
return "[]object"
if isinstance(value, dict):
keys = sorted(value.keys())
if len(keys) == 0 or OBJECTS_ONLY:
return "object"
list_key = str(keys)
if list_key in type_refs:
return type_refs[list_key]
type_name = type_name_unused(name)
typ = {}
for k in keys:
typ[str(k)] = {
"title": str(k).replace("_", " ").title(),
"type": detect_type(k, value[k]),
"description": str(k).replace("_", " ").capitalize(),
}
type_refs[list_key] = type_name
types[str(type_name)] = typ
return str(type_name)
def dump_to_spec(sections):
return spec_template.render(sections=sections)
def build_spec(item):
if not isinstance(item, dict):
raise "Not a object. You must start with a JSON object, not an array or any other type: %s" % item
for key, value in iteritems(item):
output[str(key)] = {
"title": str(key).replace("_", " ").title(),
"type": detect_type(key, value),
"description": str(key).replace("_", " ").capitalize(),
}
typesection = {"types": types}
outputsection = {"output": output}
sections = {}
sections.update(typesection)
sections.update(outputsection)
print(dump_to_spec(sections))
build_spec(data)