go-jsonschema icon indicating copy to clipboard operation
go-jsonschema copied to clipboard

Fails to generate schema for github-workflow

Open frezbo opened this issue 1 year ago • 3 comments

Trying to generate schema for github workflow from https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/github-workflow.json

❯ gojsonschema -v -p main github-workflow.json
go-jsonschema: Loading github-workflow.json
go-jsonschema: Failed: error parsing from file github-workflow.json: error parsing JSON file github-workflow.json: failed to unmarshal JSON: failed to unmarshal schema: failed to unmarshal type: failed to unmarshal type: failed to unmarshal type: failed to unmarshal type: failed to unmarshal type: json: cannot unmarshal array into Go value of type schemas.ObjectAsType

frezbo avatar Sep 01 '23 05:09 frezbo

Hi @frezbo , thanks for the heads up, I will take a look as soon as I can :)

omissis avatar Sep 01 '23 07:09 omissis

I had this diff trying to debug, didn't spent too much time, seems some fields are defined as list whereas the code expects strings

diff --git pkg/schemas/model.go pkg/schemas/model.go
index 82c0d24..4a986ac 100644
--- pkg/schemas/model.go
+++ pkg/schemas/model.go
@@ -26,6 +26,7 @@ package schemas
 import (
 	"encoding/json"
 	"fmt"
+	"os"
 )
 
 // Schema is the root schema.
@@ -40,7 +41,7 @@ type Schema struct {
 func (s *Schema) UnmarshalJSON(data []byte) error {
 	var unmarshSchema unmarshalerSchema
 	if err := json.Unmarshal(data, &unmarshSchema); err != nil {
-		return fmt.Errorf("failed to unmarshal schema: %w", err)
+		return fmt.Errorf("failed to unmarshal schema into base: %w", err)
 	}
 
 	// Fall back to id if $id is not present.
@@ -54,7 +55,7 @@ func (s *Schema) UnmarshalJSON(data []byte) error {
 	}
 
 	if err := json.Unmarshal(data, &legacySchema); err != nil {
-		return fmt.Errorf("failed to unmarshal schema: %w", err)
+		return fmt.Errorf("failed to unmarshal schema into legacy: %w", err)
 	}
 
 	if unmarshSchema.Definitions == nil && legacySchema.Definitions != nil {
@@ -156,6 +157,30 @@ type Type struct {
 	GoJSONSchemaExtension *GoJSONSchemaExtension `json:"goJSONSchema,omitempty"` //nolint:tagliatelle // breaking change
 }
 
+func lineAndCharacter(input string, offset int) (line int, character int, err error) {
+	lf := rune(0x0A)
+
+	if offset > len(input) || offset < 0 {
+		return 0, 0, fmt.Errorf("Couldn't find offset %d within the input.", offset)
+	}
+
+	// Humans tend to count from 1.
+	line = 1
+
+	for i, b := range input {
+		if b == lf {
+			line++
+			character = 0
+		}
+		character++
+		if i == offset {
+			break
+		}
+	}
+
+	return line, character, nil
+}
+
 // UnmarshalJSON accepts booleans as schemas where `true` is equivalent to `{}`
 // and `false` is equivalent to `{"not": {}}`.
 func (value *Type) UnmarshalJSON(raw []byte) error {
@@ -172,7 +197,20 @@ func (value *Type) UnmarshalJSON(raw []byte) error {
 
 	var obj ObjectAsType
 	if err := json.Unmarshal(raw, &obj); err != nil {
-		return fmt.Errorf("failed to unmarshal type: %w", err)
+		if jsonError, ok := err.(*json.UnmarshalTypeError); ok {
+			fmt.Println("field: ", jsonError.Field)
+			fmt.Println("struct: ", jsonError.Struct)
+			fmt.Println("type: ", jsonError.Type)
+			fmt.Println("value: ", jsonError.Value)
+			fmt.Println("offser: ", jsonError.Offset)
+			fmt.Println("raw: ", string(raw))
+			line, character, lcErr := lineAndCharacter(string(raw), int(jsonError.Offset))
+			fmt.Fprintf(os.Stderr, "test %d failed with error: Cannot parse JSON schema due to a syntax error at line %d, character %d: %v\n", 0, line, character, jsonError.Error())
+			if lcErr != nil {
+				fmt.Fprintf(os.Stderr, "Couldn't find the line and character position of the error due to error %v\n", lcErr)
+			}
+		}
+		return fmt.Errorf("failed to unmarshal type as onjectastype: %w", err)
 	}
 
 	// Take care of legacy fields from older RFC versions.
@@ -182,7 +220,7 @@ func (value *Type) UnmarshalJSON(raw []byte) error {
 		Definitions  Definitions      `json:"definitions,omitempty"` // Section 5.26.
 	}{}
 	if err := json.Unmarshal(raw, &legacyObj); err != nil {
-		return fmt.Errorf("failed to unmarshal type: %w", err)
+		return fmt.Errorf("failed to unmarshal type legacyObj: %w", err)
 	}
 
 	if legacyObj.Definitions != nil && obj.Definitions == nil {

frezbo avatar Sep 01 '23 08:09 frezbo

I have the same issue with parsing https://raw.githubusercontent.com/CycloneDX/specification/1.5/schema/bom-1.5.schema.json. The issue is with the definition of LicenseChoice, where it is an array of oneOf structure choices, I believe.

skandragon avatar Oct 19 '23 15:10 skandragon