omissis / go-jsonschema

A tool to generate Go data types from JSON Schema definitions.
MIT License
560 stars 89 forks source link

Fails to generate schema for github-workflow #112

Open frezbo opened 1 year ago

frezbo commented 1 year ago

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
omissis commented 1 year ago

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

frezbo commented 1 year ago

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 {
skandragon commented 10 months ago

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.