From 81b1685b5b5fc9c29a3cdb6bd2daefd2a445b95d Mon Sep 17 00:00:00 2001 From: Pedro Lisboa Date: Mon, 6 Jul 2026 17:54:54 +0000 Subject: [PATCH] feat: make allow_extra_fields as default --- CHANGES.md | 99 +++++--- JSONSCHEMA.md | 59 ++--- ppx/jsonschema/attrs.ml | 14 ++ ppx/jsonschema/attrs.mli | 6 + ppx/jsonschema/ppx_deriving_jsonschema.ml | 44 +++- ppx/jsonschema/test/extra_fields.t | 32 +++ ppx/jsonschema/test/shared/cases.ml | 9 + .../test/shared/generate_schemas_cases.ml | 3 + ppx/jsonschema/test/test.expected.ml | 214 ++++++++++++------ ppx/jsonschema/test/test.melange.expected.ml | 214 ++++++++++++------ .../test/test_schemas.expected.json | 165 +++++++++----- 11 files changed, 592 insertions(+), 267 deletions(-) create mode 100644 ppx/jsonschema/test/extra_fields.t diff --git a/CHANGES.md b/CHANGES.md index 711c3d4..4e3fe9a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,9 +5,18 @@ plain string constants. - PPX: Respect the `[@json.name "..."]` attribute in `of_json` error messages. -- **[breaking]** PPX: Ignore extra JSON object fields by default in the native +- PPX: Ignore extra JSON object fields by default in the native PPX, matching the Melange PPX. Add `[@json.disallow_extra_fields]` for records and inline records that should reject unknown keys. +- PPX: `[@@deriving jsonschema]` now generates + `"additionalProperties": true` for records by default, matching the JSON + derivers which ignore unknown object keys. Add + `[@@jsonschema.disallow_extra_fields]` (and + `[@jsonschema.disallow_extra_fields]` on inline records in variants) to opt + back into strict objects (`"additionalProperties": false`). + `[@@jsonschema.allow_extra_fields]` is still accepted for backwards + compatibility but is now a no-op; combining it with `disallow_extra_fields` + is rejected. - Library: Add `Melange_json.unknown_variant_case`, a record type with fields `tag : string` and `payload : Melange_json.t list option`, meant to be referenced as the argument of a catch-all constructor (see @@ -111,86 +120,104 @@ ## Old versions changes (from bs-json) ### 5.0.4 -* Rewrote `Encode.list` to be stack-safe and much faster. + +- Rewrote `Encode.list` to be stack-safe and much faster. ### 5.0.2 -* Added `Json.Decode.id` + +- Added `Json.Decode.id` ### 5.0.1 -* Dual licensed as LGPL-3.0 and MPL-2.0. MPL is mostly equivalent to LGPL but + +- Dual licensed as LGPL-3.0 and MPL-2.0. MPL is mostly equivalent to LGPL but relaxes its restriction on linking, which works better with the JavaScript packaging and distribution model. ### 5.0.0 -* Removed deprecated `arrayOf` encoder -* Renamed `dict` encoder to `jsonDict` -* Added new `dict` encoder that takes an additional encoder argument used to + +- Removed deprecated `arrayOf` encoder +- Renamed `dict` encoder to `jsonDict` +- Added new `dict` encoder that takes an additional encoder argument used to encode the contained values, and so it's consistent with the respective `dict` decoder. ### 4.0.0 -* Bumped `bs-platform` peer dependency to 5.0.4 to stop the compiler's + +- Bumped `bs-platform` peer dependency to 5.0.4 to stop the compiler's complaining. ### 3.0.0 -* Replace usage of `Js.Date.toJSON` with `Js.Date.toJSONUsafe`, which is exactly + +- Replace usage of `Js.Date.toJSON` with `Js.Date.toJSONUsafe`, which is exactly the same, just to avoid deprecation warnings for end users (Thanks Bob!) -* Requires `bs-platform` >= 4.0.2 +- Requires `bs-platform` >= 4.0.2 ### 2.0.0 -* Removed `Json.Decode.boolean`, `Json.Encode.boolean`, + +- Removed `Json.Decode.boolean`, `Json.Encode.boolean`, `Json.Encode.booleanArray` -* Requires `bs-platform` >= 3.0.0 +- Requires `bs-platform` >= 3.0.0 ### 1.3.1 -* Reverted commits that broke backwards compatibility despite only affecting the + +- Reverted commits that broke backwards compatibility despite only affecting the implementation ### 1.3.0 -* Deprecated `Json.Decode.boolean`, `Json.Encode.boolean`, + +- Deprecated `Json.Decode.boolean`, `Json.Encode.boolean`, `Json.Encode.booleanArray` -* Added `Json.Encode.boolArray` +- Added `Json.Encode.boolArray` ### 1.2.0 -* Added `Json.Encode.char` and `Json.Decode.char` + +- Added `Json.Encode.char` and `Json.Decode.char` ### 1.1.0 -* Added "stack traces" to higher-order decoders, making it easier to find the + +- Added "stack traces" to higher-order decoders, making it easier to find the location of an error. ### 1.0.1 -* Moved repository from `reasonml-community/bs-json` to `glennsl/bs-json` -* Renamed NPM package from `bs-json` to `@glennsl/bs-json` + +- Moved repository from `reasonml-community/bs-json` to `glennsl/bs-json` +- Renamed NPM package from `bs-json` to `@glennsl/bs-json` ### 1.0.0 -* Replaced `Json.Encoder.array` with `Json.Encode.arrayOf` renamed to `array`. + +- Replaced `Json.Encoder.array` with `Json.Encode.arrayOf` renamed to `array`. Deprecated `arrayOf` alias. -* Added `Json.parse`, `Json.parseOrRaise`, `Json.stringify` -* Added `date` encoder and decoder -* Added `tuple2`/`tuple3`/`tuple4` encoders and decoders -* Fixed bug where js integers > 32-bit were rejected as integers by +- Added `Json.parse`, `Json.parseOrRaise`, `Json.stringify` +- Added `date` encoder and decoder +- Added `tuple2`/`tuple3`/`tuple4` encoders and decoders +- Fixed bug where js integers > 32-bit were rejected as integers by Json.Decode.int (#15) ### 0.2.4 -* Added `Json.Encode.bool` -* Added `Json.Encode.pair` -* Added `Json.Encode.withDefault` -* Added `Json.Encode.nullable` -* Added `Json.Encode.arrayOf` -* Added `Json.Encode.jsonArray` as replacement for `Json.Encode.array` -* Deprecated `Json.Encode.array` + +- Added `Json.Encode.bool` +- Added `Json.Encode.pair` +- Added `Json.Encode.withDefault` +- Added `Json.Encode.nullable` +- Added `Json.Encode.arrayOf` +- Added `Json.Encode.jsonArray` as replacement for `Json.Encode.array` +- Deprecated `Json.Encode.array` ### 0.2.3 -* Fixed embarrassing bug where an API was used that isn't available on IE + +- Fixed embarrassing bug where an API was used that isn't available on IE (honestly more embarrassed on behalf of IE though) ### 0.2.2 -* Added `Json.Decode.pair` + +- Added `Json.Decode.pair` ### 0.2.1 -* Added `Json.Encode.list` + +- Added `Json.Encode.list` ### 0.2.0 -* Breaking: Renamed `Json.Encode.object_` to `Json.Encode.dict` -* Added `Json.Encode.object_` taking a list of properties instead of a + +- Breaking: Renamed `Json.Encode.object_` to `Json.Encode.dict` +- Added `Json.Encode.object_` taking a list of properties instead of a Json.Dict.t as before diff --git a/JSONSCHEMA.md b/JSONSCHEMA.md index 9d2a86f..972a707 100644 --- a/JSONSCHEMA.md +++ b/JSONSCHEMA.md @@ -80,14 +80,14 @@ Such a type will be turned into a JSON schema like this: "street": { "type": "string" } }, "required": [ "zip", "city", "street" ], - "additionalProperties": false + "additionalProperties": true }, "email": { "type": "string" }, "age": { "type": "integer" }, "name": { "type": "string" } }, "required": [ "address", "age", "name" ], - "additionalProperties": false + "additionalProperties": true } ``` @@ -368,7 +368,7 @@ type t = { }, }, "required": [ "name" ], - "additionalProperties": false + "additionalProperties": true } ``` @@ -389,7 +389,7 @@ type t = { }, }, "required": [], - "additionalProperties": false + "additionalProperties": true } ``` #### Result @@ -615,11 +615,13 @@ type t = #### Records -Records are converted to `{ "type": "object", "properties": {...}, "required": [...], "additionalProperties": false }`. +Records are converted to `{ "type": "object", "properties": {...}, "required": [...], "additionalProperties": true }`. The fields of type `option` are not included in the `required` list. -By default, additionalProperties are not allowed in objects. To allow additionalProperties, use the `allow_extra_fields` attribute: +By default, additional properties are allowed in objects, matching the JSON +derivers which ignore unknown object keys. To reject unknown keys and generate +a strict schema, use the `disallow_extra_fields` attribute: ```ocaml type company = { @@ -627,23 +629,28 @@ type company = { employees : int; } [@@deriving jsonschema] -[@@jsonschema.allow_extra_fields] +[@@jsonschema.disallow_extra_fields] ``` -This annotation will generate a schema with `"additionalProperties": true`, allowing for additional fields not defined in the record: +This annotation will generate a schema with `"additionalProperties": false`, +rejecting fields not defined in the record: ```json { "type": "object", "properties": { "name": { "type": "string" }, - "age": { "type": "integer" } + "employees": { "type": "integer" } }, - "required": [ "name", "age" ], - "additionalProperties": true + "required": [ "name", "employees" ], + "additionalProperties": false } ``` +`[@@jsonschema.allow_extra_fields]` is still accepted for backwards +compatibility but is now a no-op (allowing extra fields is the default); +combining it with `disallow_extra_fields` on the same type is an error. + When the JSON object keys differ from the ocaml field names, users can specify the corresponding JSON key implicitly using `[@key "field"]`, for example: ```ocaml @@ -656,16 +663,16 @@ type t = { #### Inline Records in Variants -You can use the `[@jsonschema.allow_extra_fields]` attribute on a constructor with an inline record to allow additional fields in that record: +Inline records in variants also allow additional fields by default. Use the `[@jsonschema.disallow_extra_fields]` attribute on a constructor with an inline record to reject unknown keys for that record: ```ocaml -type inline_record_with_extra_fields = - | User of { name : string; email : string } [@jsonschema.allow_extra_fields] +type inline_record_with_strict_fields = + | User of { name : string; email : string } [@jsonschema.disallow_extra_fields] | Guest of { ip : string } [@@deriving jsonschema] ``` -This will generate a schema that allows additional fields for the `User` variant's record but not for the `Guest` variant: +This will generate a schema that rejects additional fields for the `User` variant's record but allows them for the `Guest` variant: ```json { @@ -681,7 +688,7 @@ This will generate a schema that allows additional fields for the `User` variant "name": { "type": "string" } }, "required": [ "email", "name" ], - "additionalProperties": true + "additionalProperties": false } ], "unevaluatedItems": false, @@ -696,7 +703,7 @@ This will generate a schema that allows additional fields for the `User` variant "type": "object", "properties": { "ip": { "type": "string" } }, "required": [ "ip" ], - "additionalProperties": false + "additionalProperties": true } ], "unevaluatedItems": false, @@ -803,7 +810,7 @@ type tree = "value": { "type": "integer" } }, "required": [ "right", "left", "value" ], - "additionalProperties": false + "additionalProperties": true } ], "unevaluatedItems": false, @@ -894,7 +901,7 @@ This generates `expr_jsonschema` containing all definitions in `$defs`: "cond": { "$ref": "#/$defs/expr" } }, "required": [ "then_", "cond" ], - "additionalProperties": false + "additionalProperties": true } ], "unevaluatedItems": false, @@ -941,7 +948,7 @@ type t = { "name": { "description": "The user's full name", "type": "string" } }, "required": [ "name" ], - "additionalProperties": false + "additionalProperties": true } ``` @@ -962,7 +969,7 @@ type t = { "name": { "description": "The user's full name", "type": "string" } }, "required": [ "name" ], - "additionalProperties": false + "additionalProperties": true } ``` @@ -983,7 +990,7 @@ type t = { "name": { "format": "date-time", "type": "string" } }, "required": [ "name" ], - "additionalProperties": false + "additionalProperties": true } ``` @@ -1004,7 +1011,7 @@ type t = { "score": { "maximum": 100, "type": "integer" } }, "required": [ "score" ], - "additionalProperties": false + "additionalProperties": true } ``` @@ -1025,7 +1032,7 @@ type t = { "score": { "minimum": 0, "type": "integer" } }, "required": [ "score" ], - "additionalProperties": false + "additionalProperties": true } ``` @@ -1062,7 +1069,7 @@ type t = { "status": { "default": [ "Active" ], "anyOf": [ ... ] } }, "required": [], - "additionalProperties": false + "additionalProperties": true } ``` @@ -1087,7 +1094,7 @@ type t = { "created_at": { "format": "date-time", "description": "Creation timestamp", "type": "string" } }, "required": [ "score", "created_at" ], - "additionalProperties": false + "additionalProperties": true } ``` diff --git a/ppx/jsonschema/attrs.ml b/ppx/jsonschema/attrs.ml index d564aed..fa65473 100644 --- a/ppx/jsonschema/attrs.ml +++ b/ppx/jsonschema/attrs.ml @@ -44,6 +44,18 @@ let jsonschema_cd_allow_extra_fields = Ast_pattern.(pstr nil) (fun () -> ()) +let jsonschema_td_disallow_extra_fields = + Attribute.declare "jsonschema.disallow_extra_fields" + Attribute.Context.type_declaration + Ast_pattern.(pstr nil) + (fun () -> ()) + +let jsonschema_cd_disallow_extra_fields = + Attribute.declare "jsonschema.disallow_extra_fields" + Attribute.Context.constructor_declaration + Ast_pattern.(pstr nil) + (fun () -> ()) + let jsonschema_option = Attribute.declare_flag "jsonschema.option" Attribute.Context.label_declaration @@ -175,6 +187,8 @@ let attributes = Attribute.T jsonschema_polymorphic_variant_name; Attribute.T jsonschema_td_allow_extra_fields; Attribute.T jsonschema_cd_allow_extra_fields; + Attribute.T jsonschema_td_disallow_extra_fields; + Attribute.T jsonschema_cd_disallow_extra_fields; Attribute.T jsonschema_option; Attribute.T jsonschema_ld_description; Attribute.T jsonschema_td_description; diff --git a/ppx/jsonschema/attrs.mli b/ppx/jsonschema/attrs.mli index bb16977..33330c6 100644 --- a/ppx/jsonschema/attrs.mli +++ b/ppx/jsonschema/attrs.mli @@ -26,6 +26,12 @@ val jsonschema_td_allow_extra_fields : val jsonschema_cd_allow_extra_fields : (Ppxlib.constructor_declaration, unit -> unit) Ppxlib.Attribute.t +val jsonschema_td_disallow_extra_fields : + (Ppxlib.type_declaration, unit -> unit) Ppxlib.Attribute.t + +val jsonschema_cd_disallow_extra_fields : + (Ppxlib.constructor_declaration, unit -> unit) Ppxlib.Attribute.t + val jsonschema_option : Ppxlib.label_declaration Ppxlib.Attribute.flag val jsonschema_ld_description : diff --git a/ppx/jsonschema/ppx_deriving_jsonschema.ml b/ppx/jsonschema/ppx_deriving_jsonschema.ml index 333b9c2..d7f6302 100644 --- a/ppx/jsonschema/ppx_deriving_jsonschema.ml +++ b/ppx/jsonschema/ppx_deriving_jsonschema.ml @@ -220,9 +220,18 @@ and schema_of_poly_variant ~loc ~(config : Attrs.config) let v = Schema.variants ~loc ~compact_variants constrs in v, is_rec +let resolve_additional_properties ~loc ~allow ~disallow = + match allow, disallow with + | true, true -> + Location.raise_errorf ~loc + "ppx_deriving_jsonschema: [@jsonschema.allow_extra_fields] and \ + [@jsonschema.disallow_extra_fields] are mutually exclusive" + | _, true -> false + | _, false -> true + (* Returns (schema_expression, is_recursive) *) let schema_of_record ~loc ~(config : Attrs.config) ?(recursive_types = []) - fields allow_extra_fields = + fields additional_properties = let fields, required, is_rec = List.fold_left (fun (fields, required, is_rec) @@ -287,7 +296,8 @@ let schema_of_record ~loc ~(config : Attrs.config) ?(recursive_types = []) "type", `String "object"; "properties", `Assoc [%e elist ~loc fields]; "required", `List [%e elist ~loc required]; - "additionalProperties", `Bool [%e ebool ~loc allow_extra_fields]; + ( "additionalProperties", + `Bool [%e ebool ~loc additional_properties] ); ]], is_rec ) @@ -310,13 +320,21 @@ let schema_of_variants ~loc ~(config : Attrs.config) in match pcd_args with | Pcstr_record label_declarations -> - let allow_extra_fields = + let allow = Attribute.get Attrs.jsonschema_cd_allow_extra_fields var |> Option.is_some in + let disallow = + Attribute.get Attrs.jsonschema_cd_disallow_extra_fields var + |> Option.is_some + in + let additional_properties = + resolve_additional_properties ~loc:var.pcd_loc ~allow + ~disallow + in let obj_schema, obj_rec = schema_of_record ~loc ~config ~recursive_types - label_declarations allow_extra_fields + label_declarations additional_properties in ( `Tag (name, [ obj_schema ], description_opt) :: variants, is_rec || obj_rec ) @@ -338,10 +356,6 @@ let schema_of_variants ~loc ~(config : Attrs.config) let schema_of_type_decl ~loc ~(config : Attrs.config) ~recursive_types type_decl = let type_name = type_decl.ptype_name.txt in - let allow_extra_fields = - Attribute.get Attrs.jsonschema_td_allow_extra_fields type_decl - |> Option.is_some - in let params = List.map (fun tp -> (get_type_param_name tp).txt) @@ -358,9 +372,21 @@ let schema_of_type_decl ~loc ~(config : Attrs.config) ~recursive_types in type_name, schema, is_rec, params | Ptype_record label_declarations -> + let allow = + Attribute.get Attrs.jsonschema_td_allow_extra_fields type_decl + |> Option.is_some + in + let disallow = + Attribute.get Attrs.jsonschema_td_disallow_extra_fields type_decl + |> Option.is_some + in + let additional_properties = + resolve_additional_properties ~loc:type_decl.ptype_loc ~allow + ~disallow + in let schema, is_rec = schema_of_record ~loc ~config ~recursive_types label_declarations - allow_extra_fields + additional_properties in type_name, schema, is_rec, params | Ptype_abstract -> ( diff --git a/ppx/jsonschema/test/extra_fields.t b/ppx/jsonschema/test/extra_fields.t new file mode 100644 index 0000000..2a3fdae --- /dev/null +++ b/ppx/jsonschema/test/extra_fields.t @@ -0,0 +1,32 @@ +Extra fields are allowed by default (matching the Melange JSON deriver), so a +plain record produces "additionalProperties": true. + + $ cat > default.ml << 'EOF' + > type t = { x : int } [@@deriving jsonschema] + > EOF + $ ./pp.exe -deriving-keep-w32 both --impl default.ml -o default.actual.ml + $ grep additionalProperties default.actual.ml + ("additionalProperties", (`Bool true))] in + +[@@jsonschema.disallow_extra_fields] opts into strict objects with +"additionalProperties": false. + + $ cat > strict.ml << 'EOF' + > type t = { x : int } [@@deriving jsonschema] [@@jsonschema.disallow_extra_fields] + > EOF + $ ./pp.exe -deriving-keep-w32 both --impl strict.ml -o strict.actual.ml + $ grep additionalProperties strict.actual.ml + ("additionalProperties", (`Bool false))] in + +Using [@jsonschema.allow_extra_fields] and [@jsonschema.disallow_extra_fields] +together is rejected. + + $ cat > conflict.ml << 'EOF' + > type t = { x : int } [@@deriving jsonschema] [@@jsonschema.allow_extra_fields] [@@jsonschema.disallow_extra_fields] + > EOF + $ ./pp.exe -deriving-keep-w32 both --impl conflict.ml -o conflict.actual.ml + File "conflict.ml", line 1, characters 0-115: + 1 | type t = { x : int } [@@deriving jsonschema] [@@jsonschema.allow_extra_fields] [@@jsonschema.disallow_extra_fields] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Error: ppx_deriving_jsonschema: [@jsonschema.allow_extra_fields] and [@jsonschema.disallow_extra_fields] are mutually exclusive + [1] diff --git a/ppx/jsonschema/test/shared/cases.ml b/ppx/jsonschema/test/shared/cases.ml index 8bdd3de..7b1bbc8 100644 --- a/ppx/jsonschema/test/shared/cases.ml +++ b/ppx/jsonschema/test/shared/cases.ml @@ -159,6 +159,15 @@ type x_without_extra = { x : int } type x_with_extra = { x : int; y : int } [@@deriving jsonschema] [@@allow_extra_fields] +type strict_obj = { x : int } +[@@deriving jsonschema] [@@jsonschema.disallow_extra_fields] + +type inline_record_disallow_extra_fields = + | User of { name : string; email : string } + [@jsonschema.disallow_extra_fields] + | Guest of { ip : string } +[@@deriving jsonschema] + type 'url generic_link_traffic = { title : string option; url : 'url } [@@deriving jsonschema] diff --git a/ppx/jsonschema/test/shared/generate_schemas_cases.ml b/ppx/jsonschema/test/shared/generate_schemas_cases.ml index 5388ffb..1c8fd17 100644 --- a/ppx/jsonschema/test/shared/generate_schemas_cases.ml +++ b/ppx/jsonschema/test/shared/generate_schemas_cases.ml @@ -65,6 +65,9 @@ let schemas = Ppx_deriving_jsonschema_runtime.json_schema t11_jsonschema; Ppx_deriving_jsonschema_runtime.json_schema nested_obj_jsonschema; Ppx_deriving_jsonschema_runtime.json_schema x_without_extra_jsonschema; + Ppx_deriving_jsonschema_runtime.json_schema strict_obj_jsonschema; + Ppx_deriving_jsonschema_runtime.json_schema + inline_record_disallow_extra_fields_jsonschema; Ppx_deriving_jsonschema_runtime.json_schema (generic_link_traffic_jsonschema string_jsonschema); Ppx_deriving_jsonschema_runtime.json_schema diff --git a/ppx/jsonschema/test/test.expected.ml b/ppx/jsonschema/test/test.expected.ml index aa0c7cb..7e13bf2 100644 --- a/ppx/jsonschema/test/test.expected.ml +++ b/ppx/jsonschema/test/test.expected.ml @@ -113,7 +113,7 @@ include pairs)) | other -> other)))])); ("required", (`List [`String "m2"; `String "m"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -383,7 +383,7 @@ include `String "comment"; `String "kind_f"; `String "date"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -412,7 +412,7 @@ include (`Assoc [("$ref", (`String "#/$defs/recursive_record"))]))); ("a", int_jsonschema)])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -494,7 +494,7 @@ include [`String "right"; `String "left"; `String "value"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -515,7 +515,7 @@ include ("properties", (`Assoc [("y", string_jsonschema); ("x", int_jsonschema)])); ("required", (`List [`String "y"; `String "x"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -544,7 +544,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/bar"))])))])); ("required", (`List [`String "bar"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_bar = `Assoc [("type", (`String "object")); @@ -554,7 +554,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/foo"))])))])); ("required", (`List [`String "foo"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -571,7 +571,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/bar"))])))])); ("required", (`List [`String "bar"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_bar = `Assoc [("type", (`String "object")); @@ -581,7 +581,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/foo"))])))])); ("required", (`List [`String "foo"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -670,7 +670,7 @@ include [`String "else_"; `String "then_"; `String "cond"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -750,7 +750,7 @@ include [`String "else_"; `String "then_"; `String "cond"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -774,7 +774,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("x", int_jsonschema)])); ("required", (`List [`String "x"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -792,7 +792,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("y", string_jsonschema)])); ("required", (`List [`String "y"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -829,7 +829,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_b"))])))])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_b = `Assoc [("type", (`String "object")); @@ -842,7 +842,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "d"; `String "c"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_c = `Assoc [("type", (`String "object")); @@ -855,7 +855,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "f"; `String "g"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -877,7 +877,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_b"))])))])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_b = `Assoc [("type", (`String "object")); @@ -890,7 +890,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "d"; `String "c"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_c = `Assoc [("type", (`String "object")); @@ -903,7 +903,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "f"; `String "g"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -925,7 +925,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_b"))])))])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_b = `Assoc [("type", (`String "object")); @@ -938,7 +938,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "d"; `String "c"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_c = `Assoc [("type", (`String "object")); @@ -951,7 +951,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "f"; `String "g"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -1252,7 +1252,7 @@ include pairs)) | other -> other)))])); ("required", (`List [`String "m"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1325,7 +1325,7 @@ include (`Assoc [("$ref", (`String "#/$defs/numbers"))])); ("player", string_jsonschema)])); ("required", (`List [`String "scores_ref"; `String "player"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1355,7 +1355,7 @@ include ("street", string_jsonschema)])); ("required", (`List [`String "zip"; `String "city"; `String "street"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1400,7 +1400,7 @@ include `String "email"; `String "age"; `String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1446,7 +1446,7 @@ include `String "email"; `String "age"; `String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1515,7 +1515,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("ip", string_jsonschema)])); ("required", (`List [`String "ip"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -1926,7 +1926,7 @@ include pairs)) | other -> other)))])); ("required", (`List [`String "obj2"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2020,6 +2020,84 @@ include ppx_pairs)) | other -> other)[@@warning "-32-39"] end[@@ocaml.doc "@inline"][@@merlin.hide ] +type strict_obj = { + x: int }[@@deriving jsonschema][@@jsonschema.disallow_extra_fields ] +include + struct + let strict_obj_jsonschema = + let ppx_eds = ref [] in + let ppx_result = + `Assoc + [("type", (`String "object")); + ("properties", (`Assoc [("x", int_jsonschema)])); + ("required", (`List [`String "x"])); + ("additionalProperties", (`Bool false))] in + match !ppx_eds with + | [] -> ppx_result + | ppx_defs -> + (match ppx_result with + | `Assoc ppx_pairs -> + `Assoc (("$defs", (`Assoc ppx_defs)) :: + (Stdlib.List.filter + (fun (k, _) -> not (Stdlib.String.equal k "$defs")) + ppx_pairs)) + | other -> other)[@@warning "-32-39"] + end[@@ocaml.doc "@inline"][@@merlin.hide ] +type inline_record_disallow_extra_fields = + | User of { + name: string ; + email: string } [@jsonschema.disallow_extra_fields ] + | Guest of { + ip: string } [@@deriving jsonschema] +include + struct + let inline_record_disallow_extra_fields_jsonschema = + let ppx_eds = ref [] in + let ppx_result = + `Assoc + [("anyOf", + (`List + [`Assoc + [("type", (`String "array")); + ("prefixItems", + (`List + [`Assoc [("const", (`String "User"))]; + `Assoc + [("type", (`String "object")); + ("properties", + (`Assoc + [("email", string_jsonschema); + ("name", string_jsonschema)])); + ("required", + (`List [`String "email"; `String "name"])); + ("additionalProperties", (`Bool false))]])); + ("unevaluatedItems", (`Bool false)); + ("minItems", (`Int 2)); + ("maxItems", (`Int 2))]; + `Assoc + [("type", (`String "array")); + ("prefixItems", + (`List + [`Assoc [("const", (`String "Guest"))]; + `Assoc + [("type", (`String "object")); + ("properties", (`Assoc [("ip", string_jsonschema)])); + ("required", (`List [`String "ip"])); + ("additionalProperties", (`Bool true))]])); + ("unevaluatedItems", (`Bool false)); + ("minItems", (`Int 2)); + ("maxItems", (`Int 2))]]))] in + match !ppx_eds with + | [] -> ppx_result + | ppx_defs -> + (match ppx_result with + | `Assoc ppx_pairs -> + `Assoc (("$defs", (`Assoc ppx_defs)) :: + (Stdlib.List.filter + (fun (k, _) -> not (Stdlib.String.equal k "$defs")) + ppx_pairs)) + | other -> other)[@@warning "-32-39"] + end[@@ocaml.doc "@inline"][@@merlin.hide ] type 'url generic_link_traffic = { title: string option ; url: 'url }[@@deriving jsonschema] @@ -2035,7 +2113,7 @@ include [("url", url); ("title", (option_jsonschema string_jsonschema))])); ("required", (`List [`String "url"; `String "title"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2055,7 +2133,7 @@ include let ppx_result = match generic_link_traffic_jsonschema string_jsonschema with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> - `Assoc (("$id", (`String "file://shared/cases.ml:165")) :: + `Assoc (("$id", (`String "file://shared/cases.ml:174")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other in @@ -2122,7 +2200,7 @@ include [("label", string_jsonschema); ("second", b); ("first", a)])); ("required", (`List [`String "label"; `String "second"; `String "first"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2195,7 +2273,7 @@ include let ppx_result = match either_jsonschema a b with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> - `Assoc (("$id", (`String "file://shared/cases.ml:175")) :: + `Assoc (("$id", (`String "file://shared/cases.ml:184")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other in @@ -2242,7 +2320,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "max_results"; `String "query"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2285,7 +2363,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2320,7 +2398,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2424,7 +2502,7 @@ include (`Assoc [("y", int_jsonschema); ("x", int_jsonschema)])); ("required", (`List [`String "y"; `String "x"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -2468,7 +2546,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "age"; `String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2493,7 +2571,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("name", string_jsonschema)])); ("required", (`List [`String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2526,7 +2604,7 @@ include ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "field"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2653,7 +2731,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2828,7 +2906,7 @@ include ("drop_simple", (option_jsonschema string_jsonschema)); ("plain", (option_jsonschema string_jsonschema))])); ("required", (`List [`String "plain"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2889,7 +2967,7 @@ include ("option_value", (option_jsonschema string_jsonschema)); ("required_value", int_jsonschema)])); ("required", (`List [`String "required_value"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2924,14 +3002,14 @@ include | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> `Assoc - (("$id", (`String "file://shared/cases.ml:307")) + (("$id", (`String "file://shared/cases.ml:316")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2985,7 +3063,7 @@ include ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "with_format"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3115,7 +3193,7 @@ include (list_jsonschema (`Assoc [("$ref", (`String "#/$defs/self_ref"))])))])); ("required", (`List [`String "children"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc ([("self_ref", ppx_body_self_ref)] @ (!ppx_eds)))); ("$ref", (`String "#/$defs/self_ref"))][@@warning "-32-39"] @@ -3137,7 +3215,7 @@ include | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> `Assoc - (("$id", (`String "file://shared/cases.ml:334")) :: + (("$id", (`String "file://shared/cases.ml:343")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) @@ -3146,13 +3224,13 @@ include ((match self_ref_jsonschema with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> `Assoc - (("$id", (`String "file://shared/cases.ml:334")) :: + (("$id", (`String "file://shared/cases.ml:343")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other)))])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3220,7 +3298,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:343")) + (`String "file://shared/cases.ml:352")) :: (Stdlib.List.filter (fun (k, _) -> @@ -3368,7 +3446,7 @@ include `Assoc (("maximum", (`Int 100)) :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "field"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3463,7 +3541,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "label"; `String "score"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3586,7 +3664,7 @@ include `Assoc (("minimum", (`Int 0)) :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "ratio"; `String "score"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3770,7 +3848,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("to", a); ("from", a)])); ("required", (`List [`String "to"; `String "from"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3805,7 +3883,7 @@ include ("properties", (`Assoc [("score", (option_jsonschema int_jsonschema))])); ("required", (`List [`String "score"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3847,7 +3925,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:431")) + (`String "file://shared/cases.ml:440")) :: (Stdlib.List.filter (fun (k, _) -> @@ -3887,7 +3965,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:428")) + (`String "file://shared/cases.ml:437")) :: (Stdlib.List.filter (fun (k, _) -> @@ -3907,7 +3985,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:427")) + (`String "file://shared/cases.ml:436")) :: (Stdlib.List.filter (fun (k, _) -> @@ -3984,7 +4062,7 @@ include `Assoc (("default", (`Int 0)) :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4060,7 +4138,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:440")) + (`String "file://shared/cases.ml:449")) :: (Stdlib.List.filter (fun (k, _) -> @@ -4076,7 +4154,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4115,7 +4193,7 @@ include ("properties", (`Assoc [("foo", (option_jsonschema int_jsonschema))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4147,7 +4225,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:458")) + (`String "file://shared/cases.ml:467")) :: (Stdlib.List.filter (fun (k, _) -> @@ -4164,7 +4242,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4429,7 +4507,7 @@ module Generated_code_must_qualify_stdlib = :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4450,7 +4528,7 @@ module Generated_code_must_qualify_stdlib = let ppx_result = match wrapper_with_shadowed_stdlib_jsonschema int_jsonschema with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> - `Assoc (("$id", (`String "file://shared/cases.ml:502")) :: + `Assoc (("$id", (`String "file://shared/cases.ml:511")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other in @@ -4514,7 +4592,7 @@ module Nonrec_type_alias = let ppx_result = match foo_jsonschema with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> - `Assoc (("$id", (`String "file://shared/cases.ml:510")) + `Assoc (("$id", (`String "file://shared/cases.ml:519")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) diff --git a/ppx/jsonschema/test/test.melange.expected.ml b/ppx/jsonschema/test/test.melange.expected.ml index c73f05d..5261ac5 100644 --- a/ppx/jsonschema/test/test.melange.expected.ml +++ b/ppx/jsonschema/test/test.melange.expected.ml @@ -113,7 +113,7 @@ include pairs)) | other -> other)))])); ("required", (`List [`String "m2"; `String "m"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -383,7 +383,7 @@ include `String "comment"; `String "kind_f"; `String "date"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -412,7 +412,7 @@ include (`Assoc [("$ref", (`String "#/$defs/recursive_record"))]))); ("a", int_jsonschema)])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -494,7 +494,7 @@ include [`String "right"; `String "left"; `String "value"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -515,7 +515,7 @@ include ("properties", (`Assoc [("y", string_jsonschema); ("x", int_jsonschema)])); ("required", (`List [`String "y"; `String "x"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -544,7 +544,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/bar"))])))])); ("required", (`List [`String "bar"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_bar = `Assoc [("type", (`String "object")); @@ -554,7 +554,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/foo"))])))])); ("required", (`List [`String "foo"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -571,7 +571,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/bar"))])))])); ("required", (`List [`String "bar"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_bar = `Assoc [("type", (`String "object")); @@ -581,7 +581,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/foo"))])))])); ("required", (`List [`String "foo"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -670,7 +670,7 @@ include [`String "else_"; `String "then_"; `String "cond"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -750,7 +750,7 @@ include [`String "else_"; `String "then_"; `String "cond"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -774,7 +774,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("x", int_jsonschema)])); ("required", (`List [`String "x"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -792,7 +792,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("y", string_jsonschema)])); ("required", (`List [`String "y"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -829,7 +829,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_b"))])))])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_b = `Assoc [("type", (`String "object")); @@ -842,7 +842,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "d"; `String "c"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_c = `Assoc [("type", (`String "object")); @@ -855,7 +855,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "f"; `String "g"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -877,7 +877,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_b"))])))])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_b = `Assoc [("type", (`String "object")); @@ -890,7 +890,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "d"; `String "c"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_c = `Assoc [("type", (`String "object")); @@ -903,7 +903,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "f"; `String "g"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -925,7 +925,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_b"))])))])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_b = `Assoc [("type", (`String "object")); @@ -938,7 +938,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "d"; `String "c"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in let ppx_body_node_c = `Assoc [("type", (`String "object")); @@ -951,7 +951,7 @@ include (option_jsonschema (`Assoc [("$ref", (`String "#/$defs/node_a"))])))])); ("required", (`List [`String "f"; `String "g"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc @@ -1252,7 +1252,7 @@ include pairs)) | other -> other)))])); ("required", (`List [`String "m"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1325,7 +1325,7 @@ include (`Assoc [("$ref", (`String "#/$defs/numbers"))])); ("player", string_jsonschema)])); ("required", (`List [`String "scores_ref"; `String "player"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1355,7 +1355,7 @@ include ("street", string_jsonschema)])); ("required", (`List [`String "zip"; `String "city"; `String "street"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1400,7 +1400,7 @@ include `String "email"; `String "age"; `String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1446,7 +1446,7 @@ include `String "email"; `String "age"; `String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -1515,7 +1515,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("ip", string_jsonschema)])); ("required", (`List [`String "ip"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -1926,7 +1926,7 @@ include pairs)) | other -> other)))])); ("required", (`List [`String "obj2"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2020,6 +2020,84 @@ include ppx_pairs)) | other -> other)[@@warning "-32-39"] end[@@ocaml.doc "@inline"][@@merlin.hide ] +type strict_obj = { + x: int }[@@deriving jsonschema][@@jsonschema.disallow_extra_fields ] +include + struct + let strict_obj_jsonschema = + let ppx_eds = ref [] in + let ppx_result = + `Assoc + [("type", (`String "object")); + ("properties", (`Assoc [("x", int_jsonschema)])); + ("required", (`List [`String "x"])); + ("additionalProperties", (`Bool false))] in + match !ppx_eds with + | [] -> ppx_result + | ppx_defs -> + (match ppx_result with + | `Assoc ppx_pairs -> + `Assoc (("$defs", (`Assoc ppx_defs)) :: + (Stdlib.List.filter + (fun (k, _) -> not (Stdlib.String.equal k "$defs")) + ppx_pairs)) + | other -> other)[@@warning "-32-39"] + end[@@ocaml.doc "@inline"][@@merlin.hide ] +type inline_record_disallow_extra_fields = + | User of { + name: string ; + email: string } [@jsonschema.disallow_extra_fields ] + | Guest of { + ip: string } [@@deriving jsonschema] +include + struct + let inline_record_disallow_extra_fields_jsonschema = + let ppx_eds = ref [] in + let ppx_result = + `Assoc + [("anyOf", + (`List + [`Assoc + [("type", (`String "array")); + ("prefixItems", + (`List + [`Assoc [("const", (`String "User"))]; + `Assoc + [("type", (`String "object")); + ("properties", + (`Assoc + [("email", string_jsonschema); + ("name", string_jsonschema)])); + ("required", + (`List [`String "email"; `String "name"])); + ("additionalProperties", (`Bool false))]])); + ("unevaluatedItems", (`Bool false)); + ("minItems", (`Int 2)); + ("maxItems", (`Int 2))]; + `Assoc + [("type", (`String "array")); + ("prefixItems", + (`List + [`Assoc [("const", (`String "Guest"))]; + `Assoc + [("type", (`String "object")); + ("properties", (`Assoc [("ip", string_jsonschema)])); + ("required", (`List [`String "ip"])); + ("additionalProperties", (`Bool true))]])); + ("unevaluatedItems", (`Bool false)); + ("minItems", (`Int 2)); + ("maxItems", (`Int 2))]]))] in + match !ppx_eds with + | [] -> ppx_result + | ppx_defs -> + (match ppx_result with + | `Assoc ppx_pairs -> + `Assoc (("$defs", (`Assoc ppx_defs)) :: + (Stdlib.List.filter + (fun (k, _) -> not (Stdlib.String.equal k "$defs")) + ppx_pairs)) + | other -> other)[@@warning "-32-39"] + end[@@ocaml.doc "@inline"][@@merlin.hide ] type 'url generic_link_traffic = { title: string option ; url: 'url }[@@deriving jsonschema] @@ -2035,7 +2113,7 @@ include [("url", url); ("title", (option_jsonschema string_jsonschema))])); ("required", (`List [`String "url"; `String "title"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2055,7 +2133,7 @@ include let ppx_result = match generic_link_traffic_jsonschema string_jsonschema with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> - `Assoc (("$id", (`String "file://shared/cases.ml:165")) :: + `Assoc (("$id", (`String "file://shared/cases.ml:174")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other in @@ -2122,7 +2200,7 @@ include [("label", string_jsonschema); ("second", b); ("first", a)])); ("required", (`List [`String "label"; `String "second"; `String "first"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2195,7 +2273,7 @@ include let ppx_result = match either_jsonschema a b with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> - `Assoc (("$id", (`String "file://shared/cases.ml:175")) :: + `Assoc (("$id", (`String "file://shared/cases.ml:184")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other in @@ -2242,7 +2320,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "max_results"; `String "query"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2285,7 +2363,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2320,7 +2398,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2424,7 +2502,7 @@ include (`Assoc [("y", int_jsonschema); ("x", int_jsonschema)])); ("required", (`List [`String "y"; `String "x"])); - ("additionalProperties", (`Bool false))]])); + ("additionalProperties", (`Bool true))]])); ("unevaluatedItems", (`Bool false)); ("minItems", (`Int 2)); ("maxItems", (`Int 2))]]))] in @@ -2468,7 +2546,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "age"; `String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2493,7 +2571,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("name", string_jsonschema)])); ("required", (`List [`String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2526,7 +2604,7 @@ include ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "field"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2653,7 +2731,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "name"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2828,7 +2906,7 @@ include ("drop_simple", (option_jsonschema string_jsonschema)); ("plain", (option_jsonschema string_jsonschema))])); ("required", (`List [`String "plain"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2889,7 +2967,7 @@ include ("option_value", (option_jsonschema string_jsonschema)); ("required_value", int_jsonschema)])); ("required", (`List [`String "required_value"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2924,14 +3002,14 @@ include | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> `Assoc - (("$id", (`String "file://shared/cases.ml:307")) + (("$id", (`String "file://shared/cases.ml:316")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -2985,7 +3063,7 @@ include ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "with_format"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3115,7 +3193,7 @@ include (list_jsonschema (`Assoc [("$ref", (`String "#/$defs/self_ref"))])))])); ("required", (`List [`String "children"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in `Assoc [("$defs", (`Assoc ([("self_ref", ppx_body_self_ref)] @ (!ppx_eds)))); ("$ref", (`String "#/$defs/self_ref"))][@@warning "-32-39"] @@ -3137,7 +3215,7 @@ include | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> `Assoc - (("$id", (`String "file://shared/cases.ml:334")) :: + (("$id", (`String "file://shared/cases.ml:343")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) @@ -3146,13 +3224,13 @@ include ((match self_ref_jsonschema with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> `Assoc - (("$id", (`String "file://shared/cases.ml:334")) :: + (("$id", (`String "file://shared/cases.ml:343")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other)))])); ("required", (`List [`String "b"; `String "a"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3220,7 +3298,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:343")) + (`String "file://shared/cases.ml:352")) :: (Stdlib.List.filter (fun (k, _) -> @@ -3368,7 +3446,7 @@ include `Assoc (("maximum", (`Int 100)) :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "field"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3463,7 +3541,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "label"; `String "score"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3586,7 +3664,7 @@ include `Assoc (("minimum", (`Int 0)) :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [`String "ratio"; `String "score"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3780,7 +3858,7 @@ include [("type", (`String "object")); ("properties", (`Assoc [("to", a); ("from", a)])); ("required", (`List [`String "to"; `String "from"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3821,7 +3899,7 @@ include ("properties", (`Assoc [("score", (option_jsonschema int_jsonschema))])); ("required", (`List [`String "score"])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -3863,7 +3941,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:431")) + (`String "file://shared/cases.ml:440")) :: (Stdlib.List.filter (fun (k, _) -> @@ -3903,7 +3981,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:428")) + (`String "file://shared/cases.ml:437")) :: (Stdlib.List.filter (fun (k, _) -> @@ -3923,7 +4001,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:427")) + (`String "file://shared/cases.ml:436")) :: (Stdlib.List.filter (fun (k, _) -> @@ -4000,7 +4078,7 @@ include `Assoc (("default", (`Int 0)) :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4079,7 +4157,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:440")) + (`String "file://shared/cases.ml:449")) :: (Stdlib.List.filter (fun (k, _) -> @@ -4095,7 +4173,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4141,7 +4219,7 @@ include ("properties", (`Assoc [("foo", (option_jsonschema int_jsonschema))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4173,7 +4251,7 @@ include Stdlib.List.mem_assoc "$defs" pairs -> `Assoc (("$id", - (`String "file://shared/cases.ml:458")) + (`String "file://shared/cases.ml:467")) :: (Stdlib.List.filter (fun (k, _) -> @@ -4190,7 +4268,7 @@ include :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4455,7 +4533,7 @@ module Generated_code_must_qualify_stdlib = :: ppx_fields) | ppx_other -> ppx_other)))])); ("required", (`List [])); - ("additionalProperties", (`Bool false))] in + ("additionalProperties", (`Bool true))] in match !ppx_eds with | [] -> ppx_result | ppx_defs -> @@ -4476,7 +4554,7 @@ module Generated_code_must_qualify_stdlib = let ppx_result = match wrapper_with_shadowed_stdlib_jsonschema int_jsonschema with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> - `Assoc (("$id", (`String "file://shared/cases.ml:502")) :: + `Assoc (("$id", (`String "file://shared/cases.ml:511")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) pairs)) | other -> other in @@ -4540,7 +4618,7 @@ module Nonrec_type_alias = let ppx_result = match foo_jsonschema with | `Assoc pairs when Stdlib.List.mem_assoc "$defs" pairs -> - `Assoc (("$id", (`String "file://shared/cases.ml:510")) + `Assoc (("$id", (`String "file://shared/cases.ml:519")) :: (Stdlib.List.filter (fun (k, _) -> not (Stdlib.String.equal k "$id")) diff --git a/ppx/jsonschema/test/test_schemas.expected.json b/ppx/jsonschema/test/test_schemas.expected.json index 3f2907f..be8a153 100644 --- a/ppx/jsonschema/test/test_schemas.expected.json +++ b/ppx/jsonschema/test/test_schemas.expected.json @@ -81,7 +81,7 @@ } }, "required": [ "m2", "m" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -276,7 +276,7 @@ "native_int", "unit", "string_ref", "bunch_of_bytes", "c", "t", "l", "a", "opt_int", "comment", "kind_f", "date" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -291,7 +291,7 @@ "a": { "type": "integer" } }, "required": [ "b", "a" ], - "additionalProperties": false + "additionalProperties": true } }, "$ref": "#/$defs/recursive_record" @@ -346,7 +346,7 @@ "value": { "type": "integer" } }, "required": [ "right", "left", "value" ], - "additionalProperties": false + "additionalProperties": true } ], "unevaluatedItems": false, @@ -363,7 +363,7 @@ "type": "object", "properties": { "y": { "type": "string" }, "x": { "type": "integer" } }, "required": [ "y", "x" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -376,7 +376,7 @@ } }, "required": [ "bar" ], - "additionalProperties": false + "additionalProperties": true }, "bar": { "type": "object", @@ -386,7 +386,7 @@ } }, "required": [ "foo" ], - "additionalProperties": false + "additionalProperties": true } }, "$ref": "#/$defs/foo" @@ -402,7 +402,7 @@ } }, "required": [ "bar" ], - "additionalProperties": false + "additionalProperties": true }, "bar": { "type": "object", @@ -412,7 +412,7 @@ } }, "required": [ "foo" ], - "additionalProperties": false + "additionalProperties": true } }, "$ref": "#/$defs/bar" @@ -481,7 +481,7 @@ "cond": { "$ref": "#/$defs/expr" } }, "required": [ "else_", "then_", "cond" ], - "additionalProperties": false + "additionalProperties": true } ], "unevaluatedItems": false, @@ -498,14 +498,14 @@ "type": "object", "properties": { "x": { "type": "integer" } }, "required": [ "x" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "y": { "type": "string" } }, "required": [ "y" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -521,7 +521,7 @@ } }, "required": [ "b", "a" ], - "additionalProperties": false + "additionalProperties": true }, "node_b": { "type": "object", @@ -534,7 +534,7 @@ } }, "required": [ "d", "c" ], - "additionalProperties": false + "additionalProperties": true }, "node_c": { "type": "object", @@ -547,7 +547,7 @@ } }, "required": [ "f", "g" ], - "additionalProperties": false + "additionalProperties": true } }, "$ref": "#/$defs/node_a" @@ -613,7 +613,7 @@ "value": { "type": "integer" } }, "required": [ "right", "left", "value" ], - "additionalProperties": false + "additionalProperties": true } ], "unevaluatedItems": false, @@ -696,7 +696,7 @@ "native_int", "unit", "string_ref", "bunch_of_bytes", "c", "t", "l", "a", "opt_int", "comment", "kind_f", "date" ], - "additionalProperties": false + "additionalProperties": true } }, { @@ -772,7 +772,7 @@ "native_int", "unit", "string_ref", "bunch_of_bytes", "c", "t", "l", "a", "opt_int", "comment", "kind_f", "date" ], - "additionalProperties": false + "additionalProperties": true } } }, @@ -848,7 +848,7 @@ "native_int", "unit", "string_ref", "bunch_of_bytes", "c", "t", "l", "a", "opt_int", "comment", "kind_f", "date" ], - "additionalProperties": false + "additionalProperties": true }, { "type": "string" } ], @@ -930,7 +930,7 @@ "native_int", "unit", "string_ref", "bunch_of_bytes", "c", "t", "l", "a", "opt_int", "comment", "kind_f", "date" ], - "additionalProperties": false + "additionalProperties": true }, { "type": "string" } ], @@ -1013,7 +1013,7 @@ "native_int", "unit", "string_ref", "bunch_of_bytes", "c", "t", "l", "a", "opt_int", "comment", "kind_f", "date" ], - "additionalProperties": false + "additionalProperties": true }, { "type": "integer" } ], @@ -1095,7 +1095,7 @@ "native_int", "unit", "string_ref", "bunch_of_bytes", "c", "t", "l", "a", "opt_int", "comment", "kind_f", "date" ], - "additionalProperties": false + "additionalProperties": true } } }, @@ -1132,7 +1132,7 @@ } }, "required": [ "m" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1176,7 +1176,7 @@ "player": { "type": "string" } }, "required": [ "scores_ref", "player" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1190,14 +1190,14 @@ "street": { "type": "string" } }, "required": [ "zip", "city", "street" ], - "additionalProperties": false + "additionalProperties": true }, "email": { "type": [ "string", "null" ] }, "age": { "type": "integer" }, "name": { "type": "string" } }, "required": [ "address", "email", "age", "name" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1210,7 +1210,7 @@ "street": { "type": "string" } }, "required": [ "zip", "city", "street" ], - "additionalProperties": false + "additionalProperties": true } }, "type": "object", @@ -1226,7 +1226,7 @@ "retreat_address", "work_address", "home_address", "email", "age", "name" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1263,7 +1263,7 @@ "type": "object", "properties": { "ip": { "type": "string" } }, "required": [ "ip" ], - "additionalProperties": false + "additionalProperties": true } ], "unevaluatedItems": false, @@ -1486,7 +1486,7 @@ } }, "required": [ "obj2" ], - "additionalProperties": false + "additionalProperties": true } }, "required": [ "obj1" ], @@ -1499,6 +1499,51 @@ "required": [ "x" ], "additionalProperties": true }, + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { "x": { "type": "integer" } }, + "required": [ "x" ], + "additionalProperties": false + }, + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "anyOf": [ + { + "type": "array", + "prefixItems": [ + { "const": "User" }, + { + "type": "object", + "properties": { + "email": { "type": "string" }, + "name": { "type": "string" } + }, + "required": [ "email", "name" ], + "additionalProperties": false + } + ], + "unevaluatedItems": false, + "minItems": 2, + "maxItems": 2 + }, + { + "type": "array", + "prefixItems": [ + { "const": "Guest" }, + { + "type": "object", + "properties": { "ip": { "type": "string" } }, + "required": [ "ip" ], + "additionalProperties": true + } + ], + "unevaluatedItems": false, + "minItems": 2, + "maxItems": 2 + } + ] + }, { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", @@ -1507,7 +1552,7 @@ "title": { "type": [ "string", "null" ] } }, "required": [ "url", "title" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1517,7 +1562,7 @@ "title": { "type": [ "string", "null" ] } }, "required": [ "url", "title" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1547,7 +1592,7 @@ "first": { "type": "integer" } }, "required": [ "label", "second", "first" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1606,7 +1651,7 @@ } }, "required": [ "max_results", "query" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1620,7 +1665,7 @@ "name": { "description": "The user's full name", "type": "string" } }, "required": [ "name" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1632,7 +1677,7 @@ } }, "required": [], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1690,7 +1735,7 @@ "x": { "type": "integer" } }, "required": [ "y", "x" ], - "additionalProperties": false + "additionalProperties": true } ], "unevaluatedItems": false, @@ -1708,14 +1753,14 @@ "name": { "description": "The user's full name", "type": "string" } }, "required": [ "age", "name" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "name": { "type": "string" } }, "required": [ "name" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1724,7 +1769,7 @@ "field": { "description": "explicit wins", "type": "string" } }, "required": [ "field" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1767,7 +1812,7 @@ } }, "required": [ "name" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1842,7 +1887,7 @@ "plain": { "type": [ "string", "null" ] } }, "required": [ "plain" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1862,7 +1907,7 @@ "required_value": { "type": "integer" } }, "required": [ "required_value" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1874,7 +1919,7 @@ } }, "required": [], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1888,7 +1933,7 @@ "with_format": { "format": "date-time", "type": "string" } }, "required": [ "with_format" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -1963,7 +2008,7 @@ "type": "object", "properties": { "b": { - "$id": "file://ppx/jsonschema/test/cases.ml:334", + "$id": "file://ppx/jsonschema/test/cases.ml:343", "$defs": { "self_ref": { "type": "object", @@ -1974,13 +2019,13 @@ } }, "required": [ "children" ], - "additionalProperties": false + "additionalProperties": true } }, "$ref": "#/$defs/self_ref" }, "a": { - "$id": "file://ppx/jsonschema/test/cases.ml:334", + "$id": "file://ppx/jsonschema/test/cases.ml:343", "$defs": { "self_ref": { "type": "object", @@ -1991,14 +2036,14 @@ } }, "required": [ "children" ], - "additionalProperties": false + "additionalProperties": true } }, "$ref": "#/$defs/self_ref" } }, "required": [ "b", "a" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -2086,7 +2131,7 @@ "prefixItems": [ { "const": "BoolAtom" }, { - "$id": "file://ppx/jsonschema/test/cases.ml:343", + "$id": "file://ppx/jsonschema/test/cases.ml:352", "$defs": { "filter": { "anyOf": [ @@ -2151,7 +2196,7 @@ "type": "object", "properties": { "field": { "maximum": 100, "type": "integer" } }, "required": [ "field" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -2177,7 +2222,7 @@ } }, "required": [ "label", "score" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -2204,7 +2249,7 @@ "score": { "minimum": 0, "maximum": 100, "type": "integer" } }, "required": [ "ratio", "score" ], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -2255,7 +2300,7 @@ "from": { "type": "integer" } }, "required": [ "to", "from" ], - "additionalProperties": false + "additionalProperties": true }, "empty_list": { "default": [], @@ -2272,7 +2317,7 @@ "type": "object", "properties": { "score": { "type": [ "integer", "null" ] } }, "required": [ "score" ], - "additionalProperties": false + "additionalProperties": true }, "variant": { "default": [ "A" ], @@ -2320,7 +2365,7 @@ "score": { "default": 0, "type": [ "integer", "null" ] } }, "required": [], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -2347,7 +2392,7 @@ } }, "required": [], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -2358,11 +2403,11 @@ "type": "object", "properties": { "foo": { "type": [ "integer", "null" ] } }, "required": [], - "additionalProperties": false + "additionalProperties": true } }, "required": [], - "additionalProperties": false + "additionalProperties": true }, { "$schema": "https://json-schema.org/draft/2020-12/schema",