Skip to content

Commit

Permalink
encoding/jsonschema: support minContains and maxContains keywords
Browse files Browse the repository at this point in the history
This change add support for JSON Schema `minContains` and `maxContains`
keywords.

Change-Id: I4e27444e212d36adc120918386db54aaae3d98fc
Signed-off-by: haoqixu <[email protected]>
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1199615
Unity-Result: CUE porcuepine <[email protected]>
Reviewed-by: Roger Peppe <[email protected]>
TryBot-Result: CUEcueckoo <[email protected]>
  • Loading branch information
haoqixu authored and rogpeppe committed Aug 28, 2024
1 parent dcfc2d4 commit 4093ccf
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 3 deletions.
2 changes: 2 additions & 0 deletions encoding/jsonschema/constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ var constraints = []*constraint{
p3("allOf", constraintAllOf),
p3("anyOf", constraintAnyOf),
p2d("const", constraintConst, vfrom(versionDraft06)),
p1d("minContains", constraintMinContains, vfrom(version2019_09)),
p1d("maxContains", constraintMaxContains, vfrom(version2019_09)),
p2d("contains", constraintContains, vfrom(versionDraft06)),
p2d("contentEncoding", constraintContentEncoding, vfrom(versionDraft07)),
p2d("contentMediaType", constraintContentMediaType, vfrom(versionDraft07)),
Expand Down
40 changes: 37 additions & 3 deletions encoding/jsonschema/constraints_array.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package jsonschema

import (
"strconv"

"cuelang.org/go/cue"
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/token"
Expand All @@ -38,13 +40,45 @@ func constraintAdditionalItems(key string, n cue.Value, s *state) {
}
}

func constraintMinContains(key string, n cue.Value, s *state) {
p, err := n.Uint64()
if err != nil {
s.errf(n, `value of "minContains" must be a non-negative integer value`)
return
}
s.minContains = &p
}

func constraintMaxContains(key string, n cue.Value, s *state) {
p, err := n.Uint64()
if err != nil {
s.errf(n, `value of "maxContains" must be a non-negative integer value`)
return
}
s.maxContains = &p
}

func constraintContains(key string, n cue.Value, s *state) {
list := s.addImport(n, "list")
x := s.schema(n)
x = ast.NewCall(ast.NewSel(list, "MatchN"), &ast.UnaryExpr{

var min uint64 = 1
if s.minContains != nil {
min = *s.minContains
}
var c ast.Expr = &ast.UnaryExpr{
Op: token.GEQ,
X: ast.NewLit(token.INT, "1"),
}, clearPos(x))
X: ast.NewLit(token.INT, strconv.FormatUint(min, 10)),
}

if s.maxContains != nil {
c = ast.NewBinExpr(token.AND, c, &ast.UnaryExpr{
Op: token.LEQ,
X: ast.NewLit(token.INT, strconv.FormatUint(*s.maxContains, 10)),
})
}

x = ast.NewCall(ast.NewSel(list, "MatchN"), c, clearPos(x))
s.add(n, arrayType, x)
}

Expand Down
3 changes: 3 additions & 0 deletions encoding/jsonschema/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,9 @@ type state struct {
exclusiveMin bool // For OpenAPI and legacy support.
exclusiveMax bool // For OpenAPI and legacy support.

minContains *uint64
maxContains *uint64

schemaVersion schemaVersion
schemaVersionPresent bool

Expand Down
32 changes: 32 additions & 0 deletions encoding/jsonschema/testdata/contains.txtar
Original file line number Diff line number Diff line change
@@ -1,13 +1,45 @@
-- schema.yaml --
$schema: "https://json-schema.org/draft/2019-09/schema"
type: object

properties:
p1:
type: array
contains: {}

p2:
type: array
contains: {}
minContains: 0

p3:
type: array
contains: {}
maxContains: 6

p4:
type: array
contains: {}
minContains: 3
maxContains: 6

# If "contains" is not present within the same schema object, then this keyword has no effect.
p5:
type: array
minContains: 6
p6:
type: array
maxContains: 6

additionalProperties: false

-- out/decode/extract --
import "list"

@jsonschema(schema="https://json-schema.org/draft/2019-09/schema")
p1?: list.MatchN(>=1, _)
p2?: list.MatchN(>=0, _)
p3?: list.MatchN(>=1 & <=6, _)
p4?: list.MatchN(>=3 & <=6, _)
p5?: [...]
p6?: [...]

0 comments on commit 4093ccf

Please sign in to comment.