Skip to content

Commit 15f243b

Browse files
committed
encoding/jsonschema: add Config.AllowNonExistentRoot
`AllowNonExistentRoot` prevents an error when there is no value at the above Root path. Such an error can be useful to signal that the data may not be a JSON Schema, but is not always a good idea. When extracting CUE from OpenAPI documents, they are not required to contain a .components.schemas member but in the usual case of using the command line, it's probably an error if there is no such member (because it might mean that we're not using the right kind of file at all, and we're probably expecting some schemas to be present otherwise we wouldn't be invoking the cue command to extract schemas). However, in some cases, we don't want to consider it an error, so add an option to cause us to ignore a missing root. Another possibility might be to change jsonschema.Extract to return a custom error type/value, but this means that it would be harder to change the cue command to import openapi files even as CUE even when there are no definitions. Also in passing fix an error message that was not including the error that it was about. Signed-off-by: Roger Peppe <[email protected]> Change-Id: Ib9d6ef9be834a869000762bff9bc9cd4bc9bd115 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1207007 Reviewed-by: Daniel Martí <[email protected]> TryBot-Result: CUEcueckoo <[email protected]> Unity-Result: CUE porcuepine <[email protected]>
1 parent dfe3ae0 commit 15f243b

File tree

5 files changed

+29
-2
lines changed

5 files changed

+29
-2
lines changed

encoding/jsonschema/decode.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ func (d *decoder) decode(v cue.Value) *ast.File {
127127
return nil
128128
}
129129
defsRoot = v.LookupPath(defsPath)
130-
if kind := defsRoot.Kind(); kind != cue.StructKind {
130+
if !defsRoot.Exists() && d.cfg.AllowNonExistentRoot {
131+
defsRoot = v.Context().CompileString("{}")
132+
} else if defsRoot.Kind() != cue.StructKind {
131133
d.errf(defsRoot, "value at path %v must be struct containing definitions but is actually %v", d.cfg.Root, defsRoot)
132134
return nil
133135
}
@@ -904,7 +906,7 @@ func (s *state) addDefinition(n cue.Value) *definedSchema {
904906
loc.Path = relPath(n, s.root)
905907
importPath, path, err := s.cfg.MapRef(loc)
906908
if err != nil {
907-
s.errf(n, "cannot get reference for %v", loc)
909+
s.errf(n, "cannot get reference for %v: %v", loc, err)
908910
return nil
909911
}
910912
def = &definedSchema{

encoding/jsonschema/decode_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ func TestDecode(t *testing.T) {
100100
}
101101
cfg.Strict = t.HasTag("strict")
102102
cfg.StrictKeywords = cfg.StrictKeywords || t.HasTag("strictKeywords")
103+
cfg.AllowNonExistentRoot = t.HasTag("allowNonExistentRoot")
103104
cfg.StrictFeatures = t.HasTag("strictFeatures")
104105
cfg.PkgName, _ = t.Value("pkgName")
105106

encoding/jsonschema/jsonschema.go

+6
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ type Config struct {
124124
// only. Just `#` is preferred.
125125
Root string
126126

127+
// AllowNonExistentRoot holds whether it's an error when there
128+
// is no value at the above Root path. For example, when extracting
129+
// an OpenAPI schema, the #/components/schemas path might not
130+
// exist, but that could be considered OK even so.
131+
AllowNonExistentRoot bool
132+
127133
// Map maps the locations of schemas and definitions to a new location.
128134
// References are updated accordingly. A returned label must be
129135
// an identifier or string literal.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Test what happens when there's an OpenAPI schema that has no
2+
/components/schemas entry but AllowNonExistentRoot is true
3+
4+
#allowNonExistentRoot
5+
#version: openapi
6+
7+
-- schema.yaml --
8+
-- out/decode/extract --
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Test what happens when there's an OpenAPI schema that has no
2+
/components/schemas entry and AllowNonExistentRoot is false
3+
4+
#version: openapi
5+
6+
-- schema.yaml --
7+
-- out/decode/extract --
8+
ERROR:
9+
value at path #/components/schemas/ must be struct containing definitions but is actually _|_ // field not found: components

0 commit comments

Comments
 (0)