cue
cue copied to clipboard
cmd/cue: cannot use a reference via -l input jsonschema
What version of CUE are you using (cue version)?
$ cue version
cue version v0.12.0
go version go1.23.4
-buildmode exe
-compiler gc
DefaultGODEBUG asynctimerchan=1,gotypesalias=0,httpservecontentkeepheaders=1,tls3des=1,tlskyber=0,x509keypairleaf=0,x509negativeserial=1
CGO_ENABLED 1
GOARCH arm64
GOOS darwin
GOARM64 v8.0
cue.lang.version v0.12.0
Does this issue reproduce with the latest stable release?
Yes
What did you do?
❯ echo '{"$schema": "http://json-schema.org/draft-07/schema", "$id": "https://example.com/person.schema.json", "title": "Person","type": "object"}' | cue import -l title jsonschema: -
error evaluating label title: reference "title" not found
JSON schema:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://example.com/person.schema.json",
"title": "Person",
"type": "object"
}
What did you expect to see?
The same output as using json and no error:
❯ echo '{"$schema": "http://json-schema.org/draft-07/schema", "$id": "https://example.com/person.schema.json", "title": "Person","type": "object"}' | cue import -l title json: -
Person: {
$schema: "http://json-schema.org/draft-07/schema"
$id: "https://example.com/person.schema.json"
title: "Person"
type: "object"
}
JSON:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://example.com/person.schema.json",
"title": "Person",
"type": "object"
}
What did you see instead?
An error, error evaluating label title: reference "title" not found
Hi @joeriddles and welcome to CUE!
Reworking your example slightly as a standalone reproduction:
exec cue import -l title jsonschema: input
cmp input.cue input.cue.golden
-- input --
{"$schema": "http://json-schema.org/draft-07/schema", "$id": "https://example.com/person.schema.json", "title": "Person","type": "object"}
-- input.cue.golden --
#Person: {
$schema: "http://json-schema.org/draft-07/schema"
$id: "https://example.com/person.schema.json"
title: "Person"
type: "object"
}
The expectation is that this should succeed, but it fails with:
> exec cue import -l title jsonschema: input
[stderr]
error evaluating label title: reference "title" not found
[exit status 1]
FAIL: /tmp/testscript2318047493/repro.txtar/script.txtar:1: unexpected command failure
FWIW you can use the Go API to do this:
go mod tidy
go run . input
cmp input.cue input.cue.golden
-- go.mod --
module mod.example
go 1.23.5
require cuelang.org/go v0.12.0
-- main.go --
package main
import (
"flag"
"fmt"
"os"
"cuelang.org/go/cue"
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/format"
"cuelang.org/go/cue/token"
"cuelang.org/go/encoding/json"
"cuelang.org/go/encoding/jsonschema"
)
func main() {
// Iterate over the files listed as arguments, and extract a JSON Schema
// from each, using the 'title' field as the name of the definition.
flag.Parse()
ctx := cuecontext.New()
var exitCode int
for _, f := range flag.Args() {
if err := importJSONSchemaWithTitle(ctx, f); err != nil {
exitCode++
fmt.Fprintf(os.Stderr, "%v: %v\n", f, err)
}
}
os.Exit(exitCode)
}
func importJSONSchemaWithTitle(ctx *cue.Context, inputFile string) error {
byts, err := os.ReadFile(inputFile)
if err != nil {
return fmt.Errorf("failed to read %s: %v", inputFile, err)
}
expr, err := json.Extract(inputFile, byts)
if err != nil {
return fmt.Errorf("failed to extract JSON from %s: %v", inputFile, err)
}
v := ctx.BuildExpr(expr)
if err := v.Err(); err != nil {
return fmt.Errorf("failed to build CUE value: %v", err)
}
title, err := v.LookupPath(cue.ParsePath("title")).String()
if err != nil {
return fmt.Errorf("failed to lookup title from CUE value: %v", err)
}
schemaFile, err := jsonschema.Extract(v, &jsonschema.Config{
Strict: true,
})
if err != nil {
return fmt.Errorf("failed to extract JSON Schema from CUE value: %v", err)
}
schema := ctx.BuildFile(schemaFile)
if err := schema.Err(); err != nil {
return fmt.Errorf("schema was in error: %v", err)
}
def := ctx.CompileString("{}")
def = def.FillPath(cue.MakePath(cue.Def(title)), schema)
defFile := toFile(def.Syntax())
defByts, err := format.Node(defFile)
if err != nil {
return fmt.Errorf("failed to convert definition to syntax: %v", err)
}
targetFileName := inputFile + ".cue"
if err := os.WriteFile(targetFileName, defByts, 0666); err != nil {
return fmt.Errorf("failed to write %s: %v", targetFileName, err)
}
return nil
}
// toFile is a helper that we should make available in one of our APIs to
// simplify the writing of a CUE value to a file, eliding unnecessary {}'s
func toFile(n ast.Node) *ast.File {
if n == nil {
return nil
}
switch n := n.(type) {
case *ast.StructLit:
f := &ast.File{Decls: n.Elts}
ast.SetComments(f, ast.Comments(n))
return f
case ast.Expr:
ast.SetRelPos(n, token.NoSpace)
return &ast.File{Decls: []ast.Decl{&ast.EmbedDecl{Expr: n}}}
case *ast.File:
return n
default:
panic(fmt.Sprintf("Unsupported node type %T", n))
}
}
-- input --
{"$schema": "http://json-schema.org/draft-07/schema", "$id": "https://example.com/person.schema.json", "title": "Person","type": "object"}
-- input.cue.golden --
#Person: {
@jsonschema(schema="http://json-schema.org/draft-07/schema#")
@jsonschema(id="https://example.com/person.schema.json")
...
}