Skip to content

Commit

Permalink
encoding/jsonschema: fix decoding of $id
Browse files Browse the repository at this point in the history
When decoding "$id", jsonschema decoder mistakenly assumed that
the schema is an object and added an object constraint with the id tag.

This change postpones the attachment of id tag until an object
constraint is added or the schema is finalizing.

Fixes #3361

Change-Id: I7829af165af726524d48022fc87ed538b7e451cd
Signed-off-by: haoqixu <[email protected]>
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1199139
Unity-Result: CUE porcuepine <[email protected]>
Reviewed-by: Roger Peppe <[email protected]>
TryBot-Result: CUEcueckoo <[email protected]>
  • Loading branch information
haoqixu authored and mvdan committed Aug 9, 2024
1 parent a6f1b76 commit 915059d
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 9 deletions.
9 changes: 1 addition & 8 deletions encoding/jsonschema/constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package jsonschema

import (
"fmt"
"math/big"
"path"
"regexp"
Expand Down Expand Up @@ -143,13 +142,7 @@ var constraints = []*constraint{
return
}
s.id = u

obj := s.object(n)

// TODO: handle the case where this is always defined and we don't want
// to include the default value.
obj.Elts = append(obj.Elts, &ast.Attribute{
Text: fmt.Sprintf("@jsonschema(id=%q)", u)})
s.idPos = n.Pos()
}),

// Generic constraint
Expand Down
25 changes: 24 additions & 1 deletion encoding/jsonschema/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ type state struct {
exclusiveMax bool // For OpenAPI and legacy support.
jsonschema string
id *url.URL // base URI for $ref
idPos token.Pos

definitions []ast.Decl

Expand All @@ -362,9 +363,19 @@ type refs struct {
refs []*ast.Ident
}

func (s *state) idTag() *ast.Attribute {
return &ast.Attribute{
At: s.idPos,
Text: fmt.Sprintf("@jsonschema(id=%q)", s.id)}
}

func (s *state) object(n cue.Value) *ast.StructLit {
if s.obj == nil {
s.obj = &ast.StructLit{}

if s.id != nil {
s.obj.Elts = append(s.obj.Elts, s.idTag())
}
s.add(n, objectType, s.obj)
}
return s.obj
Expand All @@ -382,7 +393,8 @@ func (s *state) hasConstraints() bool {
return len(s.patterns) > 0 ||
s.title != "" ||
s.description != "" ||
s.obj != nil
s.obj != nil ||
s.id != nil
}

const allTypes = cue.NullKind | cue.BoolKind | cue.NumberKind | cue.IntKind |
Expand Down Expand Up @@ -499,6 +511,17 @@ outer:

s.linkReferences()

// If an "$id" exists and has not been included in any object constraints
if s.id != nil && s.obj == nil {
if st, ok := e.(*ast.StructLit); ok {
st.Elts = append([]ast.Decl{s.idTag()}, st.Elts...)
} else {
st = &ast.StructLit{Elts: []ast.Decl{s.idTag()}}
st.Elts = append(st.Elts, &ast.EmbedDecl{Expr: e})
e = st
}
}

return e
}

Expand Down
28 changes: 28 additions & 0 deletions encoding/jsonschema/testdata/id_in_oneOf.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- schema.json --
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://test.example/foo",
"oneOf": [
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://1.test.example/string",
"type": "string"
},
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://2.test.example/object",
"type": "object"
}
]
}

-- out/decode/cue --
@jsonschema(schema="http://json-schema.org/draft-07/schema#")
@jsonschema(id="https://test.example/foo")
{
@jsonschema(id="https://1.test.example/string")
string
} | {
@jsonschema(id="https://2.test.example/object")
...
}
12 changes: 12 additions & 0 deletions encoding/jsonschema/testdata/id_scalar.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- schema.json --
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://cuelang.org/go/encoding/openapi/testdata/id_scalar.json",

"type": "string"
}

-- out/decode/cue --
@jsonschema(schema="http://json-schema.org/draft-07/schema#")
@jsonschema(id="http://cuelang.org/go/encoding/openapi/testdata/id_scalar.json")
string

0 comments on commit 915059d

Please sign in to comment.