diff --git a/lib/generator.ml b/lib/generator.ml index df097b8..7e9aab4 100644 --- a/lib/generator.ml +++ b/lib/generator.ml @@ -19,19 +19,23 @@ let get_ref_name ref = (* OpenAPI defs *) | [ "#"; "components"; "schemas"; type_name ] -> type_name (* JSON Schema defs *) - | [ "#"; "$defs"; type_name ] -> type_name + | [ "#"; ("$defs" | "definitions"); type_name ] -> type_name | _ -> failwith - (Printf.sprintf "Unsupported ref value: %s. Supported ref URI are: #/components/schemas/* and #/$defs/*" ref) + (Printf.sprintf + "Unsupported ref value: %s. Supported ref URI are: #/components/schemas/* and #/$defs/* and #/definitions/*" + ref + ) let output = Buffer.create 16 let input_toplevel_schemas = ref [] let get_schema_by_ref ~schema ref = let defs = - match schema.defs with - | None -> !input_toplevel_schemas - | Some defs -> defs @ !input_toplevel_schemas + let defs = List.concat [ Utils.list_of_nonempty schema.defs; Utils.list_of_nonempty schema.definitions ] in + match defs with + | [] -> !input_toplevel_schemas + | defs -> defs @ !input_toplevel_schemas in List.find_map (function @@ -107,6 +111,7 @@ let merge_all_of schema = dependent_required = merge_lists (fun schema -> schema.dependent_required); format = take_first_opt (fun schema -> schema.format); defs = merge_opt_lists (fun schema -> schema.defs); + definitions = merge_opt_lists (fun schema -> schema.definitions); title = take_first_opt (fun schema -> schema.title); typ = take_first_opt (fun schema -> schema.typ); description = take_first_opt (fun schema -> schema.description); @@ -222,9 +227,10 @@ let make_atd_of_jsonschema input = let schema = Json_schema_j.schema_of_string input in let root_type_name = Option.value ~default:"root" schema.title in let defs = - match schema.defs with - | None -> [] - | Some defs -> List.map (fun (name, schema) -> name, Obj schema) defs + let defs = List.concat [ Utils.list_of_nonempty schema.defs; Utils.list_of_nonempty schema.definitions ] in + match defs with + | [] -> [] + | defs -> List.map (fun (name, schema) -> name, Obj schema) defs in make_atd_of_schemas ([ root_type_name, Obj schema ] @ defs) diff --git a/lib/json_schema.atd b/lib/json_schema.atd index 82b5095..c823111 100644 --- a/lib/json_schema.atd +++ b/lib/json_schema.atd @@ -88,6 +88,7 @@ type schema = { (* 8.2.4. re-usable JSON Schemas *) ~defs : (string * schema) list nullable; + ~definitions: (string * schema) list nullable; (* 9. basic metadata annotations *) ~title : string nullable; diff --git a/lib/utils.ml b/lib/utils.ml index 9c80728..37a639e 100644 --- a/lib/utils.ml +++ b/lib/utils.ml @@ -98,3 +98,7 @@ let shortest_list lists = lists |> List.sort (fun a b -> compare (List.length a) let nonempty_list_opt = function | [] -> None | non_empty_list -> Some non_empty_list + +let list_of_nonempty = function + | None -> [] + | Some l -> l diff --git a/tests/mocks/jsonchema_definitions.json b/tests/mocks/jsonchema_definitions.json new file mode 100644 index 0000000..b5b47af --- /dev/null +++ b/tests/mocks/jsonchema_definitions.json @@ -0,0 +1,23 @@ +{ + "$id": "https://example.com/schemas/customer", + "type": "object", + "properties": { + "first_name": { + "$ref": "#/$defs/name" + }, + "last_name": { + "$ref": "#/definitions/name" + } + }, + "required": [ + "first_name", + "last_name", + "shipping_address", + "billing_address" + ], + "definitions": { + "name": { + "type": "string" + } + } +} diff --git a/tests/smoke.t b/tests/smoke.t index c99866e..30d6344 100644 --- a/tests/smoke.t +++ b/tests/smoke.t @@ -56,3 +56,16 @@ Generate ATD out of JSON Schema that contains defs first_name: name; last_name: name; } + +Generate ATD out of JSON Schema that contains definitions (legacy support) + $ jsonschema2atd --format=jsonschema ./mocks/jsonchema_definitions.json + (* Generated by jsonschema2atd *) + type json = abstract + type int64 = int + + type name = string + + type root = { + first_name: name; + last_name: name; + }