Skip to content

Commit

Permalink
jsonschema: support definitions as an alias for $defs
Browse files Browse the repository at this point in the history
  • Loading branch information
Khady committed Feb 27, 2024
1 parent 779674b commit 25720fd
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 8 deletions.
22 changes: 14 additions & 8 deletions lib/generator.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions lib/json_schema.atd
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ type schema = {

(* 8.2.4. re-usable JSON Schemas *)
~defs <json name="$defs">: (string * schema) list <json repr="object"> nullable;
~definitions: (string * schema) list <json repr="object"> nullable;

(* 9. basic metadata annotations *)
~title : string nullable;
Expand Down
4 changes: 4 additions & 0 deletions lib/utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
23 changes: 23 additions & 0 deletions tests/mocks/jsonchema_definitions.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
13 changes: 13 additions & 0 deletions tests/smoke.t
Original file line number Diff line number Diff line change
Expand Up @@ -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 <ocaml module="Yojson.Basic" t="t"> = abstract
type int64 = int <ocaml repr="int64">

type name = string

type root = {
first_name: name;
last_name: name;
}

0 comments on commit 25720fd

Please sign in to comment.