From d9004914a998501797b9c1369bf19be9245e8d9e Mon Sep 17 00:00:00 2001 From: Adnan Bekan Date: Wed, 20 Sep 2023 21:13:46 +0200 Subject: [PATCH] Update tool with additional arguments and fix issue of JSON Schema validation Signed-off-by: Adnan Bekan --- vspec/vssexporters/vss2jsonschema.py | 80 ++++++++++++++++------------ 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/vspec/vssexporters/vss2jsonschema.py b/vspec/vssexporters/vss2jsonschema.py index dc6d2deb..e6d4125c 100644 --- a/vspec/vssexporters/vss2jsonschema.py +++ b/vspec/vssexporters/vss2jsonschema.py @@ -8,7 +8,7 @@ # # SPDX-License-Identifier: MPL-2.0 # -# Convert vspec tree to OpenAPI compatible JSON schema +# Convert vspec tree compatible JSON schema from vspec.model.vsstree import VSSNode @@ -47,20 +47,21 @@ def add_arguments(parser: argparse.ArgumentParser): - parser.description = "The JSON schema exporter does not support any additional arguments." - + parser.add_argument('--jsonschema-all-extended-attributes', action='store_true', + help="Generate all extended attributes found in the model. Should not be used with strict mode JSON Schema validators." + "(default is generating only those given by the -e/--extended-attributes parameter).") + parser.add_argument('--jsonschema-pretty', action='store_true', + help=" Pretty print JSON Schema output.") def export_node(json_dict, node, config, print_uuid): # TODO adding json schema version might be great # TODO check if needed, formating of jsonschema is also possible # tags starting with $ sign are left for custom extensions and they are not part of official JSON Schema json_dict[node.name] = { - "$VSStype": str(node.type.value), "description": node.description, } if node.is_signal() or node.is_property(): - json_dict[node.name]["$datatype"] = node.data_type_str json_dict[node.name]["type"] = type_map[node.data_type_str] # TODO map types, unless we want to keep original @@ -74,30 +75,36 @@ def export_node(json_dict, node, config, print_uuid): json_dict[node.name]["enum"] = node.allowed if node.default != "": json_dict[node.name]["default"] = node.default - if node.deprecation != "": - json_dict[node.name]["$deprecation"] = node.deprecation if node.is_struct(): # change type to object json_dict[node.type]["type"] = "object" - # in case of unit or aggregate, the attribute will be missing - try: - json_dict[node.name]["unit"] = str(node.unit.value) - except AttributeError: - pass - try: - json_dict[node.name]["$aggregate"] = node.aggregate - if node.aggregate is True: - # change type to object - json_dict[node.type]["type"] = "object" - except AttributeError: - pass - - if node.comment != "": - json_dict[node.name]["comment"] = node.comment - - if print_uuid: - json_dict[node.name]["$uuid"] = node.uuid + if config.jsonschema_all_extended_attributes: + if node.type !="": + json_dict[node.name]["x-VSStype"] = str(node.type.value) + if node.data_type_str !="": + json_dict[node.name]["x-datatype"] = node.data_type_str + if node.deprecation != "": + json_dict[node.name]["x-deprecation"] = node.deprecation + + # in case of unit or aggregate, the attribute will be missing + try: + json_dict[node.name]["x-unit"] = str(node.unit.value) + except AttributeError: + pass + try: + json_dict[node.name]["x-aggregate"] = node.aggregate + if node.aggregate == True: + #change type to object + json_dict[node.type]["type"] = "object" + except AttributeError: + pass + + if node.comment != "": + json_dict[node.name]["x-comment"] = node.comment + + if print_uuid: + json_dict[node.name]["x-uuid"] = node.uuid for k, v in node.extended_attributes.items(): json_dict[node.name][k] = v @@ -105,15 +112,15 @@ def export_node(json_dict, node, config, print_uuid): # Generate child nodes if node.is_branch() or node.is_struct(): # todo if struct, type could be linked to object and then list elements as properties - json_dict[node.name]["$children"] = {} + json_dict[node.name]["properties"] = {} for child in node.children: - export_node(json_dict[node.name]["$children"], child, config, print_uuid) + export_node(json_dict[node.name]["properties"], child, config, print_uuid) def export(config: argparse.Namespace, signal_root: VSSNode, print_uuid, data_type_root: VSSNode): - logging.info("Generating JSON chema...") + logging.info("Generating JSON schema...") indent = None - if config.json_pretty: + if config.jsonschema_pretty: logging.info("Serializing pretty JSON schema...") indent = 2 @@ -124,11 +131,18 @@ def export(config: argparse.Namespace, signal_root: VSSNode, print_uuid, data_ty if data_type_root is not None: data_types_json_schema: Dict[str, Any] = {} export_node(data_types_json_schema, data_type_root, config, print_uuid) - signals_json_schema["$ComplexDataTypes"] = data_types_json_schema - + if config.jsonschema_all_extended_attributes: + signals_json_schema["x-ComplexDataTypes"] = data_types_json_schema + + top_node = signals_json_schema.pop("Vehicle") + # Create a new JSON Schema object + json_schema = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Vehicle", + "type": "object", + **top_node} with open(config.output_file, 'w') as f: - - json.dump(signals_json_schema, f, indent=indent, sort_keys=True) + json.dump(json_schema, f, indent=indent, sort_keys=False) if __name__ == "__main__":