Skip to content

Commit

Permalink
update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
Khady committed Sep 25, 2024
1 parent 5eb4e2b commit 87a4aab
Show file tree
Hide file tree
Showing 3 changed files with 253 additions and 9 deletions.
71 changes: 62 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,30 +70,83 @@ OCaml lists and arrays are converted to `{ "type": "array", "items": { "type": "

#### Tuples

Tuples are converted to `{ "type": "array", "items": [...] }`.
Tuples are converted to `{ "type": "array", "prefixItems": [...] }`.

#### Variants and polymorphic variants
```ocaml
type t = int * string [@@deriving jsonschema]
```

Variants are converted to `{ "type": "string", "enum": [...] }` by default.
```json
{
"type": "array",
"prefixItems": [ { "type": "integer" }, { "type": "string" } ],
"unevaluatedItems": false,
"minItems": 2,
"maxItems": 2
}
```

#### Variants and polymorphic variants

if the JSON variant names differ from OCaml conventions, users can specify the corresponding JSON string explicitly using `[@name "constr"]`, for example:
By default, variants are converted to `"anyOf": [{ "const": "..." }, ...]`. This means that while the constructor names are represented as strings, any associated payload is not included.

```ocaml
type t =
| Typ [@name "type"]
| Class [@name "class"]
| Typ
| Class of string
[@@deriving jsonschema]
```

If you want to use the same encoding as [ppx_deriving_json] and [ppx_yojson_conv], you can use the `~variant_as_array` flag:
```json
{ "anyOf": [ { "const": "Typ" }, { "const": "Class" } ] }
```

To include the payload in the encoding, the `~variant_as_array` flag should be used. This flag also ensures compatibility with [ppx_deriving_json] and [ppx_yojson_conv]. In this case each constructor is represented like a tuple.

```ocaml
type t =
| Typ [@name "type"]
| Class [@name "class"]
| Typ
| Class of string
[@@deriving jsonschema ~variant_as_array]
```

```json
{
"anyOf": [
{
"type": "array",
"prefixItems": [ { "const": "Typ" } ],
"unevaluatedItems": false,
"minItems": 1,
"maxItems": 1
},
{
"type": "array",
"prefixItems": [ { "const": "Class" }, { "type": "string" } ],
"unevaluatedItems": false,
"minItems": 2,
"maxItems": 2
}
]
}
```

If the JSON variant names differ from OCaml conventions, it is possible to specify the corresponding JSON string explicitly using `[@name "constr"]`, for example:

```ocaml
type t =
| Typ [@name "type"]
| Class of string [@name "class"]
[@@deriving jsonschema]
```

```json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"anyOf": [ { "const": "type" }, { "const": "class" } ]
}
```

#### Records

Records are converted to `{ "type": "object", "properties": {...}, "required": [...] }`.
Expand Down
119 changes: 119 additions & 0 deletions test/test.expected.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1365,3 +1365,122 @@ include
}
]
} |}]]
type t1 =
| Typ
| Class of string [@@deriving jsonschema]
include
struct
let t1_jsonschema =
`Assoc
[("anyOf",
(`List
[`Assoc [("const", (`String "Typ"))];
`Assoc [("const", (`String "Class"))]]))][@@warning "-32-39"]
end[@@ocaml.doc "@inline"][@@merlin.hide ]
[%%expect_test
let "t1" =
print_schema t1_jsonschema;
[%expect
{|
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"anyOf": [ { "const": "Typ" }, { "const": "Class" } ]
} |}]]
type t2 =
| Typ
| Class of string [@@deriving jsonschema ~variant_as_array]
include
struct
let t2_jsonschema =
`Assoc
[("anyOf",
(`List
[`Assoc
[("type", (`String "array"));
("prefixItems",
(`List [`Assoc [("const", (`String "Typ"))]]));
("unevaluatedItems", (`Bool false));
("minItems", (`Int 1));
("maxItems", (`Int 1))];
`Assoc
[("type", (`String "array"));
("prefixItems",
(`List
[`Assoc [("const", (`String "Class"))];
`Assoc [("type", (`String "string"))]]));
("unevaluatedItems", (`Bool false));
("minItems", (`Int 2));
("maxItems", (`Int 2))]]))][@@warning "-32-39"]
end[@@ocaml.doc "@inline"][@@merlin.hide ]
[%%expect_test
let "t2" =
print_schema t2_jsonschema;
[%expect
{|
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"anyOf": [
{
"type": "array",
"prefixItems": [ { "const": "Typ" } ],
"unevaluatedItems": false,
"minItems": 1,
"maxItems": 1
},
{
"type": "array",
"prefixItems": [ { "const": "Class" }, { "type": "string" } ],
"unevaluatedItems": false,
"minItems": 2,
"maxItems": 2
}
]
} |}]]
type t3 =
| Typ [@name "type"]
| Class of string [@name "class"][@@deriving jsonschema]
include
struct
let t3_jsonschema =
`Assoc
[("anyOf",
(`List
[`Assoc [("const", (`String "type"))];
`Assoc [("const", (`String "class"))]]))][@@warning "-32-39"]
end[@@ocaml.doc "@inline"][@@merlin.hide ]
[%%expect_test
let "t3" =
print_schema t3_jsonschema;
[%expect
{|
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"anyOf": [ { "const": "type" }, { "const": "class" } ]
} |}]]
type t4 = (int * string)[@@deriving jsonschema]
include
struct
let t4_jsonschema =
`Assoc
[("type", (`String "array"));
("prefixItems",
(`List
[`Assoc [("type", (`String "integer"))];
`Assoc [("type", (`String "string"))]]));
("unevaluatedItems", (`Bool false));
("minItems", (`Int 2));
("maxItems", (`Int 2))][@@warning "-32-39"]
end[@@ocaml.doc "@inline"][@@merlin.hide ]
[%%expect_test
let "t4" =
print_schema t4_jsonschema;
[%expect
{|
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "array",
"prefixItems": [ { "type": "integer" }, { "type": "string" } ],
"unevaluatedItems": false,
"minItems": 2,
"maxItems": 2
} |}]]
72 changes: 72 additions & 0 deletions test/test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -940,3 +940,75 @@ let%expect_test "variant_with_payload" =
}
]
} |}]

type t1 =
| Typ
| Class of string
[@@deriving jsonschema]

let%expect_test "t1" =
print_schema t1_jsonschema;
[%expect
{|
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"anyOf": [ { "const": "Typ" }, { "const": "Class" } ]
} |}]

type t2 =
| Typ
| Class of string
[@@deriving jsonschema ~variant_as_array]

let%expect_test "t2" =
print_schema t2_jsonschema;
[%expect
{|
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"anyOf": [
{
"type": "array",
"prefixItems": [ { "const": "Typ" } ],
"unevaluatedItems": false,
"minItems": 1,
"maxItems": 1
},
{
"type": "array",
"prefixItems": [ { "const": "Class" }, { "type": "string" } ],
"unevaluatedItems": false,
"minItems": 2,
"maxItems": 2
}
]
} |}]

type t3 =
| Typ [@name "type"]
| Class of string [@name "class"]
[@@deriving jsonschema]

let%expect_test "t3" =
print_schema t3_jsonschema;
[%expect
{|
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"anyOf": [ { "const": "type" }, { "const": "class" } ]
} |}]

type t4 = int * string [@@deriving jsonschema]

let%expect_test "t4" =
print_schema t4_jsonschema;
[%expect
{|
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "array",
"prefixItems": [ { "type": "integer" }, { "type": "string" } ],
"unevaluatedItems": false,
"minItems": 2,
"maxItems": 2
} |}]

0 comments on commit 87a4aab

Please sign in to comment.