Skip to content

Commit

Permalink
Json2code: full $ref support
Browse files Browse the repository at this point in the history
Swagger only allows to refer to custom composite types via "$ref",
not via "type", whether it is about array elements or individual items.

Disallowing "type" would break existing use, so allow "$ref" to
be used interchangeably.

Signed-off-by: Alexey Bashtanov <[email protected]>
  • Loading branch information
bashtanov committed Sep 23, 2024
1 parent 1147ac2 commit d7a8500
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 7 deletions.
10 changes: 8 additions & 2 deletions scripts/seastar-json2code.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,13 @@ def is_model_valid(name, model):
return ""
properties = getitem(model[name], "properties", name)
for var in properties:
type = getitem(properties[var], "type", name + ":" + var)
try:
type = getitem(properties[var], "type", name + ":" + var)
except Exception as e:
try:
type = getitem(properties[var], "$ref", name + ":" + var)
except:
raise e
if type == "array":
items = getitem(properties[var], "items", name + ":" + var)
try:
Expand Down Expand Up @@ -563,7 +569,7 @@ def indent(s):
fprintln(hfile, create_enum_wrapper(model_name, member_name, member["enum"]))
fprintln(hfile, f" {config.jsonns}::json_element<{member_name}_wrapper> {member_name};\n")
else:
type_name = type_change(member["type"], member)
type_name = type_change(member["type"] if "type" in member else member["$ref"], member)
fprintln(hfile, f" {config.jsonns}::{type_name} {member_name};\n")
member_init += f'add(&{member_name}, "{member_name}");\n'
member_assignment += f'{member_name} = e.{member_name};\n'
Expand Down
13 changes: 11 additions & 2 deletions tests/unit/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
}
],
"models": {
"var2_referred": {
"type": "object",
"properties": {
"var21": {
"type": "string",
"description": "The inner part of the second parameter"
}
}
},
"my_object": {
"id": "my_object",
"description": "Demonstrate an object",
Expand All @@ -63,8 +72,8 @@
"description": "The first parameter in the path"
},
"var2": {
"type": "string",
"description": "The second parameter in the path"
"$ref": "var2_referred",
"description": "The second parameter in the path wrapped in an object"
},
"enum_var": {
"type": "string",
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/json2code_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def test_path_params(self):
with urllib.request.urlopen(url) as f:
response = json.loads(f.read().decode('utf-8'))
self.assertEqual(response['var1'], f'/{var1}')
self.assertEqual(response['var2'], f'/{var2}')
self.assertEqual(response['var2']['var21'], f'/{var2}')
self.assertEqual(response['enum_var'], query_enum)

def test_bad_enum(self):
Expand All @@ -69,7 +69,7 @@ def test_bad_enum(self):
with urllib.request.urlopen(url) as f:
response = json.loads(f.read().decode('utf-8'))
self.assertEqual(response['var1'], f'/{var1}')
self.assertEqual(response['var2'], f'/{var2}')
self.assertEqual(response['var2']['var21'], f'/{var2}')
self.assertEqual(response['enum_var'], 'Unknown')

def test_missing_path_param(self):
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/rest_api_httpd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ void set_routes(routes& r) {
api_json::hello_world.set(r, [] (const_req req) {
api_json::my_object obj;
obj.var1 = req.param.at("var1");
obj.var2 = req.param.at("var2");
api_json::var2_referred var2_wrapped;
var2_wrapped.var21 = req.param.at("var2");
obj.var2 = var2_wrapped;
api_json::ns_hello_world::query_enum v = api_json::ns_hello_world::str2query_enum(req.query_parameters.at("query_enum"));
// This demonstrate enum conversion
obj.enum_var = v;
Expand Down

0 comments on commit d7a8500

Please sign in to comment.