encoding/jsonschema: constraints don't imply types
This was a major bug based on the wrong assumption that
a JSON Schema constraint implies the type for that constraint.
Instead, the contraints only apply if a value is of a certain
type.
To keep diffs to a minimum, and to improve the overal output,
it now explicitly sorts literal
composit types (structs and lists) at the end of a series
of conjunctions.
Change-Id: Ice98a2bc00ae4a68170cd6cd726565a453b1187f
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6302
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/encoding/jsonschema/testdata/emptyanyof.txtar b/encoding/jsonschema/testdata/emptyanyof.txtar
new file mode 100644
index 0000000..0313e6d
--- /dev/null
+++ b/encoding/jsonschema/testdata/emptyanyof.txtar
@@ -0,0 +1,26 @@
+-- emptyanyof.json --
+{
+ "$defs": {
+ "shell": {
+ "description": "Specify a shell.",
+ "type": "string",
+ "anyOf": [
+ {
+ },
+ {
+ "enum": [
+ "bash",
+ "sh",
+ "cmd",
+ "powershell"
+ ]
+ }
+ ]
+ }
+ }
+}
+
+-- out.cue --
+_
+
+#shell: (string | ("bash" | "sh" | "cmd" | "powershell")) & string
diff --git a/encoding/jsonschema/testdata/err.txtar b/encoding/jsonschema/testdata/err.txtar
new file mode 100644
index 0000000..2175de8
--- /dev/null
+++ b/encoding/jsonschema/testdata/err.txtar
@@ -0,0 +1,20 @@
+-- type.json --
+{
+ "type": "object",
+
+ "properties": {
+ "multi": {
+ "type": [ "integer" ],
+ "minimum": 2,
+ "maximum": 3,
+ "maxLength": 5
+ }
+ },
+ "additionalProperties": false
+}
+
+-- out.err --
+constraint not allowed because type string is excluded:
+ type.json:9:22
+-- out.cue --
+multi?: int & >=2 & <=3
diff --git a/encoding/jsonschema/testdata/list.txtar b/encoding/jsonschema/testdata/list.txtar
index 3f7bd0a..c48c862 100644
--- a/encoding/jsonschema/testdata/list.txtar
+++ b/encoding/jsonschema/testdata/list.txtar
@@ -41,5 +41,5 @@
foo?: [...string]
tuple?: [string, int, 2]
has?: list.Contains(3)
-size?: [_, _, _, ...] & list.MaxItems(9) & list.UniqueItems()
+size?: list.UniqueItems() & list.MaxItems(9) & [_, _, _, ...]
additional?: [int, int, ...string]
diff --git a/encoding/jsonschema/testdata/num.txtar b/encoding/jsonschema/testdata/num.txtar
index 1968c3a..cbbd984 100644
--- a/encoding/jsonschema/testdata/num.txtar
+++ b/encoding/jsonschema/testdata/num.txtar
@@ -13,10 +13,16 @@
"maximum": 3
},
"exclusive": {
- "type": "number",
+ "type": "integer",
"exclusiveMinimum": 2,
"exclusiveMaximum": 3
},
+ "multi": {
+ "type": [ "integer", "string" ],
+ "minimum": 2,
+ "maximum": 3,
+ "maxLength": 5
+ },
"cents": {
"type": "number",
"multipleOf": 0.05
@@ -26,10 +32,14 @@
}
-- out.cue --
-import "math"
+import (
+ "strings"
+ "math"
+)
constant?: 2
several?: 1 | 2 | 3 | 4
inclusive?: >=2 & <=3
-exclusive?: >2 & <3
+exclusive?: int & >2 & <3
+multi?: int & >=2 & <=3 | strings.MaxRunes(5)
cents?: math.MultipleOf(0.05)
diff --git a/encoding/jsonschema/testdata/object.txtar b/encoding/jsonschema/testdata/object.txtar
index 9f773e1..1e6644e 100644
--- a/encoding/jsonschema/testdata/object.txtar
+++ b/encoding/jsonschema/testdata/object.txtar
@@ -53,6 +53,15 @@
"^\\P{Lo}": { "type": "integer" }
},
"additionalProperties": { "type": "string" }
+ },
+ "multi": {
+ "type": [ "object", "number" ],
+ "properties": {
+ "foo": { "type": "number" },
+ "bar": { "type": "number" }
+ },
+ "maxProperties": 5,
+ "minimum": 7
}
},
"additionalProperties": false
@@ -68,7 +77,6 @@
additional?: {
foo?: number
bar?: number
-
{[!~"^(foo|bar)$"]: string}
}
map?: [string]: string
@@ -94,6 +102,10 @@
{[=~"^\\P{Lu}" & !~"^(foo|bar)$"]: string}
{[=~"^\\P{Lo}" & !~"^(foo|bar)$"]: int}
-
{[!~"^\\P{Lu}" & !~"^\\P{Lo}" & !~"^(foo|bar)$"]: string}
}
+multi?: >=7 | struct.MaxFields(5) & {
+ foo?: number
+ bar?: number
+ ...
+}
diff --git a/encoding/jsonschema/testdata/refroot.txtar b/encoding/jsonschema/testdata/refroot.txtar
index c090506..6f33439 100644
--- a/encoding/jsonschema/testdata/refroot.txtar
+++ b/encoding/jsonschema/testdata/refroot.txtar
@@ -16,7 +16,7 @@
_schema
_schema: {
@jsonschema(schema="http://json-schema.org/draft-07/schema#")
- number | null | bool | string | [...] | {
+ null | bool | number | string | [...] | {
@jsonschema(id="http://cuelang.org/go/encoding/openapi/testdata/order.json")
value?: _
next?: _schema_1
diff --git a/encoding/jsonschema/testdata/refroot2.txtar b/encoding/jsonschema/testdata/refroot2.txtar
index 20e6361..e4a162c 100644
--- a/encoding/jsonschema/testdata/refroot2.txtar
+++ b/encoding/jsonschema/testdata/refroot2.txtar
@@ -14,7 +14,7 @@
_schema
_schema: {
@jsonschema(schema="http://json-schema.org/draft-07/schema#")
- number | null | bool | string | [...] | {
+ null | bool | number | string | [...] | {
value?: _
next?: _schema_1
...
diff --git a/encoding/jsonschema/testdata/typedis.txtar b/encoding/jsonschema/testdata/typedis.txtar
index 6bf10ac..d2a3aeb 100644
--- a/encoding/jsonschema/testdata/typedis.txtar
+++ b/encoding/jsonschema/testdata/typedis.txtar
@@ -34,8 +34,6 @@
}
]
},
-
-
"empty": {
"allOf": [
{ "type": "object" },
@@ -44,11 +42,14 @@
}
}
}
+-- out.err --
+constraint not allowed because type string is excluded:
+ type.json:39:23
-- out.cue --
// Main schema
intOrString1?: int | string
intOrString2?: int | string
-intOrString3?: int | string
-disjunction?: int | string | >=3
+intOrString3?: string | int
+disjunction?: string | int | int & >=3
empty?: _|_
...
diff --git a/encoding/jsonschema/testdata/used.txtar b/encoding/jsonschema/testdata/used.txtar
new file mode 100644
index 0000000..b22c92f
--- /dev/null
+++ b/encoding/jsonschema/testdata/used.txtar
@@ -0,0 +1,48 @@
+-- used.json --
+{
+ "$defs": {
+ "enum": {
+ "type": "string",
+ "enum": [ "a", "b", "c" ]
+ },
+ "lists": {
+ "description": "Single item or lists of various lengths.",
+ "oneOf": [
+ {
+ "type": "string",
+ "enum": [ "a", "b", "c" ]
+ },
+ {
+ "type": "array",
+ "oneOf": [
+ {
+ "items": [ { "const": "X" } ]
+ },
+ {
+ "items": [
+ { "const": "X" },
+ {
+ "type": "string",
+ "enum": [ "a", "b", "c" ]
+ }
+ ]
+ },
+ {
+ "items": [
+ { "const": "X" },
+ { "enum": [ "d", "e", "f" ] }
+ ]
+ }
+ ],
+ "additionalItems": false
+ }
+ ]
+ }
+ }
+}
+-- out.cue --
+_
+
+#enum: "a" | "b" | "c"
+
+#lists: "a" | "b" | "c" | (["X"] | ["X", "a" | "b" | "c"] | ["X", "d" | "e" | "f"])