Skip to content

Commit

Permalink
Merge properties and required fields in allOf composition
Browse files Browse the repository at this point in the history
  • Loading branch information
ixzzd committed Dec 28, 2023
1 parent f8337c3 commit a428916
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 25 deletions.
32 changes: 30 additions & 2 deletions lib/generator.ml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let process_int_type schema =
| _ -> failwith "int has unextected format"

let get_ref (ref : ref_) =
match ref |> String.split_on_char '/' |> List.rev with
match ref |> String.split_on_char '/' |> List.rev with
| type_name :: _ -> type_name
| _ -> failwith (Printf.sprintf "%s: can't resolve ref type name" ref)

Expand All @@ -36,7 +36,32 @@ let make_atd_default_value enum json_value =

let nullable = Printf.sprintf "%s nullable"

let nonempty_list_opt = function
| [] -> None
| non_empty_list -> Some non_empty_list

let rec merge_all_of schema =
match schema.all_of with
| None -> schema
| Some [] -> failwith "empty allOf is unexpected"
| Some schemas ->
let all_schemas =
schema
:: List.filter_map
(function
| Obj schema -> Some (merge_all_of schema)
| Ref _ -> None
)
schemas
in
{
schema with
properties = all_schemas |> List.filter_map (fun schema -> schema.properties) |> List.flatten |> nonempty_list_opt;
required = all_schemas |> List.map (fun schema -> schema.required) |> List.flatten;
}

let rec process_schema_type ~ancestors (schema : schema) =
let schema = merge_all_of schema in
let maybe_nullable type_ = if schema.nullable then nullable type_ else type_ in
match schema.one_of with
| Some schemas -> process_one_of ~ancestors schemas
Expand Down Expand Up @@ -134,6 +159,7 @@ type int64 = int <ocaml repr="int64">
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
Buffer.clear toplevel_definitions;
base ^ "\n" ^ process_schemas [ root_type_name, Obj schema ]

let make_atd_of_openapi input =
Expand All @@ -142,5 +168,7 @@ let make_atd_of_openapi input =
| None -> failwith "components are empty"
| Some components ->
match components.schemas with
| Some schemas -> base ^ "\n" ^ process_schemas schemas
| Some schemas ->
Buffer.clear toplevel_definitions;
base ^ "\n" ^ process_schemas schemas
| None -> failwith "components schemas are empty"
2 changes: 1 addition & 1 deletion lib/json_schema.atd
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type schema = {
~schema <json name="$schema">: string nullable;

(* 10.2.1 keywords for applying subschemas with logic *)
~all_of <json name="allOf">: schema nonempty_list nullable;
~all_of <json name="allOf">: schema or_ref nonempty_list nullable;
~any_of <json name="anyOf">: schema nonempty_list nullable;
~one_of <json name="oneOf">: schema or_ref nonempty_list nullable;
~not : schema nullable;
Expand Down
45 changes: 23 additions & 22 deletions tests/all_of.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,40 @@ let simple_test _ =
let input =
{| {
"dummy": {
"type": "object",
"properties": {
"field": {
"id": "string"
}
},
"allOf": [
{
"type": "object",
"properties": {
"field": {
"name": "string"
"type": "object",
"properties": {
"id": {
"type": "string"
}
}
},
{
"type": "object",
"properties": {
"field": {
"surname": "string"
"allOf": [
{
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
{
"type": "object",
"properties": {
"surname": {
"type": "string"
}
}
}
}
}
]
]
}
}|}
} |}
in
let output =
{|
type dummy = {
?id: string option;
?name: string option;
?surname: string option;
}
|}
in
assert_schema input output
Expand Down
1 change: 1 addition & 0 deletions tests/dune
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
(tests
(names
all_of
base
defaults
enums
Expand Down

0 comments on commit a428916

Please sign in to comment.