Skip to content

Commit

Permalink
encoding/jsonschema: schema version support
Browse files Browse the repository at this point in the history
This adds some logic for understanding JSON schema versions
which will be used to trigger version-specific behavior
in subsequent CLs.

Signed-off-by: Roger Peppe <[email protected]>
Change-Id: I91c15cbe54454d4f22a88e5ad532bfa2d03ad6f1
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1199315
Reviewed-by: Daniel Martí <[email protected]>
TryBot-Result: CUEcueckoo <[email protected]>
Unity-Result: CUE porcuepine <[email protected]>
  • Loading branch information
rogpeppe committed Aug 13, 2024
1 parent 52ae410 commit 6c26e3c
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 15 deletions.
15 changes: 14 additions & 1 deletion encoding/jsonschema/constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,20 @@ var constraints = []*constraint{
p0("$schema", func(n cue.Value, s *state) {
// Identifies this as a JSON schema and specifies its version.
// TODO: extract version.
s.jsonschema, _ = s.strValue(n)

s.schemaVersion = versionDraft07 // Reasonable default version.
str, ok := s.strValue(n)
if !ok {
// If there's no $schema value, use the default.
return
}
sv, err := parseSchemaVersion(str)
if err != nil {
s.errf(n, "invalid $schema URL %q: %v", str, err)
return
}
s.schemaVersionPresent = true
s.schemaVersion = sv
}),

p0("$id", func(n cue.Value, s *state) {
Expand Down
14 changes: 9 additions & 5 deletions encoding/jsonschema/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ func (d *decoder) schema(ref []ast.Label, v cue.Value) (a []ast.Decl) {
expr, state := root.schemaState(v, allTypes, nil, false)

tags := []string{}
if state.jsonschema != "" {
tags = append(tags, fmt.Sprintf("schema=%q", state.jsonschema))
if state.schemaVersionPresent {
// TODO use cue/literal.String
tags = append(tags, fmt.Sprintf("schema=%q", state.schemaVersion))
}

if name == nil {
Expand Down Expand Up @@ -334,9 +335,12 @@ type state struct {
deprecated bool
exclusiveMin bool // For OpenAPI and legacy support.
exclusiveMax bool // For OpenAPI and legacy support.
jsonschema string
id *url.URL // base URI for $ref
idPos token.Pos

schemaVersion schemaVersion
schemaVersionPresent bool

id *url.URL // base URI for $ref
idPos token.Pos

definitions []ast.Decl

Expand Down
7 changes: 2 additions & 5 deletions encoding/jsonschema/decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ func TestDecode(t *testing.T) {

func TestMapURL(t *testing.T) {
v := cuecontext.New().CompileString(`
$schema: "xxx"
type: "object"
properties: x: $ref: "https://something.test/foo#/definitions/blah"
`)
Expand All @@ -129,15 +128,13 @@ properties: x: $ref: "https://something.test/foo#/definitions/blah"
qt.Assert(t, qt.Equals(string(b), `
import "other.test/something:blah"
@jsonschema(schema="xxx")
x?: blah.#blah
...
`[1:]))
}

func TestMapURLErrors(t *testing.T) {
v := cuecontext.New().CompileString(`
$schema: "xxx"
type: "object"
properties: {
x: $ref: "https://something.test/foo#/definitions/x"
Expand All @@ -151,9 +148,9 @@ properties: {
})
qt.Assert(t, qt.Equals(errors.Details(err, nil), `
cannot determine import path from URL "https://something.test/foo": some error:
foo.cue:5:5
foo.cue:4:5
cannot determine import path from URL "https://something.test/foo": some error:
foo.cue:6:5
foo.cue:5:5
`[1:]))
}

Expand Down
30 changes: 30 additions & 0 deletions encoding/jsonschema/schemaversion_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions encoding/jsonschema/testdata/emptyobj.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Issue #734
-- github-workflow.json --
{
"$schema": "http://json-schema.org/draft-07/schema",
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"obj1": {
"oneOf": [
Expand All @@ -23,7 +23,7 @@
}
}
-- out/decode/cue --
@jsonschema(schema="http://json-schema.org/draft-07/schema")
@jsonschema(schema="http://json-schema.org/draft-07/schema#")
_

#obj1: null | {
Expand Down
4 changes: 2 additions & 2 deletions encoding/jsonschema/testdata/unsupported.txtar
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-- unsupported.json --
{
"$schema": "http://json-schema.org/draft-07/schema",
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"ref": {
"properties": {
Expand Down Expand Up @@ -35,7 +35,7 @@


-- out/decode/cue --
@jsonschema(schema="http://json-schema.org/draft-07/schema")
@jsonschema(schema="http://json-schema.org/draft-07/schema#")
_

#ref: null | {
Expand Down
32 changes: 32 additions & 0 deletions encoding/jsonschema/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package jsonschema

import (
"fmt"
)

//go:generate go run golang.org/x/tools/cmd/stringer -type=schemaVersion -linecomment

type schemaVersion int

const (
versionUnknown schemaVersion = iota // unknown
versionDraft04 // http://json-schema.org/draft-04/schema#
versionDraft05 // http://json-schema.org/draft-05/schema#
versionDraft06 // http://json-schema.org/draft-06/schema#
versionDraft07 // http://json-schema.org/draft-07/schema#
version2019_09 // https://json-schema.org/draft/2019-09/schema
version2020_12 // https://json-schema.org/draft/2020-12/schema

numVersions // unknown
)

func parseSchemaVersion(sv string) (schemaVersion, error) {
// If this linear search is ever a performance issue, we could
// build a map, but it doesn't seem worthwhile for now.
for i := schemaVersion(1); i < numVersions; i++ {
if sv == i.String() {
return i, nil
}
}
return 0, fmt.Errorf("$schema URI not recognized")
}

0 comments on commit 6c26e3c

Please sign in to comment.