2023-08-01 14:09:27 +00:00
|
|
|
package jsonschema
|
|
|
|
|
2023-08-15 14:28:04 +00:00
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
)
|
|
|
|
|
2023-08-01 14:09:27 +00:00
|
|
|
// defines schema for a json object
|
|
|
|
type Schema struct {
|
|
|
|
// Type of the object
|
|
|
|
Type Type `json:"type,omitempty"`
|
|
|
|
|
|
|
|
// Description of the object. This is rendered as inline documentation in the
|
|
|
|
// IDE. This is manually injected here using schema.Docs
|
|
|
|
Description string `json:"description,omitempty"`
|
|
|
|
|
|
|
|
// Schemas for the fields of an struct. The keys are the first json tag.
|
|
|
|
// The values are the schema for the type of the field
|
|
|
|
Properties map[string]*Schema `json:"properties,omitempty"`
|
|
|
|
|
|
|
|
// The schema for all values of an array
|
|
|
|
Items *Schema `json:"items,omitempty"`
|
|
|
|
|
|
|
|
// The schema for any properties not mentioned in the Schema.Properties field.
|
|
|
|
// this validates maps[string]any in bundle configuration
|
|
|
|
// OR
|
|
|
|
// A boolean type with value false. Setting false here validates that all
|
|
|
|
// properties in the config have been defined in the json schema as properties
|
|
|
|
//
|
|
|
|
// Its type during runtime will either be *Schema or bool
|
|
|
|
AdditionalProperties any `json:"additionalProperties,omitempty"`
|
|
|
|
|
|
|
|
// Required properties for the object. Any fields missing the "omitempty"
|
|
|
|
// json tag will be included
|
|
|
|
Required []string `json:"required,omitempty"`
|
|
|
|
|
|
|
|
// URI to a json schema
|
|
|
|
Reference *string `json:"$ref,omitempty"`
|
|
|
|
|
|
|
|
// Default value for the property / object
|
|
|
|
Default any `json:"default,omitempty"`
|
2023-09-05 11:08:25 +00:00
|
|
|
|
|
|
|
// Extension embeds our custom JSON schema extensions.
|
|
|
|
Extension
|
2023-08-01 14:09:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Type string
|
|
|
|
|
|
|
|
const (
|
|
|
|
InvalidType Type = "invalid"
|
|
|
|
BooleanType Type = "boolean"
|
|
|
|
StringType Type = "string"
|
|
|
|
NumberType Type = "number"
|
|
|
|
ObjectType Type = "object"
|
|
|
|
ArrayType Type = "array"
|
|
|
|
IntegerType Type = "integer"
|
|
|
|
)
|
2023-08-15 14:28:04 +00:00
|
|
|
|
|
|
|
func (schema *Schema) validate() error {
|
|
|
|
for _, v := range schema.Properties {
|
|
|
|
switch v.Type {
|
|
|
|
case NumberType, BooleanType, StringType, IntegerType:
|
|
|
|
continue
|
|
|
|
case "int", "int32", "int64":
|
|
|
|
return fmt.Errorf("type %s is not a recognized json schema type. Please use \"integer\" instead", v.Type)
|
|
|
|
case "float", "float32", "float64":
|
|
|
|
return fmt.Errorf("type %s is not a recognized json schema type. Please use \"number\" instead", v.Type)
|
|
|
|
case "bool":
|
|
|
|
return fmt.Errorf("type %s is not a recognized json schema type. Please use \"boolean\" instead", v.Type)
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("type %s is not a recognized json schema type", v.Type)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func Load(path string) (*Schema, error) {
|
|
|
|
b, err := os.ReadFile(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
schema := &Schema{}
|
|
|
|
err = json.Unmarshal(b, schema)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return schema, schema.validate()
|
|
|
|
}
|