schema

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 9, 2024 License: Apache-2.0 Imports: 7 Imported by: 2

README

 

JSight

JSight Schema Go Library

Golang Telegram support PRs Welcome License JSight on Facebook JSight on LinkedIn Twitter Follow

Alchemist Accelerator

 

Star us on GitHub — it motivates us a lot!

 

JSight Schema Go Library is a library that parses schemas written in JSight Schema language.

JSight Schema language — you have never described your data so fast. We mean it. Compare JSight Schema with JSON Schema..

JSight Schema language specification on the official website: https://jsight.io/docs/jsight-schema-0-3.
JSight Schema language specification on GitHub: https://github.com/jsightapi/specification/tree/main/versions/JSight%20Schema.

The JSight Schema Go Library is currently used as part of the JSight Server and JSight Online Editor applications.

 
Try now!

📖   Table of Contents

 

🚀   Getting Started

Prerequisites
Installing

Download the JSight Schema Go Library source code:

git clone https://github.com/jsightapi/jsight-schema-core

Go to the repository folder:

cd ./jsight-schema-core/

Install development dependencies:

(Ensure $GOPATH/bin is in the $PATH)

make deps

Download all dependencies:

go mod download

Run automated tests.

If the tests are successful, then everything is fine, and the library is working.

go test -cover ./...

 

SUPPORT: If you have any problems while launching the JSight Schema Go Library, do not hesitate to contact our support, we respond quickly:
Email: support@jsight.io
Telegram: https://t.me/jsight_support

 

📜   JSight Schema language

The JSight Schema language allows you to describe any data structures with incredible speed and convenience. You can read more about it in the JSight Schema Language Specification.

The JSight Schema language is actively used by the JSight API language, which is designed to describe API. For more information about JSight Schema within the JSight API, see the Quick Tutorial.

Mentioned below are examples of the same data schemas described using JSight Schema and JSON Schema.

Example 1. The simplest
JSight Schema 0.3 JSON Schema 2020-12
{
  "id"  : 123, // {min: 1}
  "name": "Tom"
}

Pay attention to the main feature of the JSight Schema language. The basis for a data schema is an example of valid data. Additional data requirements are specified in C-like comments. This approach greatly simplifies the data schema and makes it intuitively clear. Practice shows that such schema is very simple to create, read and edit.

For details, see the JSight Schema Language Specification, in the section “EXAMPLE”.

Star us on GitHub — it motivates us a lot!

{
    "type": "object",
    "required": [
        "id",
        "name"
    ],
    "properties": {
        "id": {
            "type": "integer",
            "minimum": 1
        },
        "name": {
            "type": "string"
        }
    },
    "examples": [{
        "id": 123,
        "name": "Tom"
    }]
}
Example 2. Nested arrays and objects
JSight Schema 0.3 JSON Schema 2020-12
{
  "productId": 1,
  "productName": "An ice sculpture",
  "price": 12.50,    // {min: 0, exclusiveMinimum: true}
  "tags": [          // {minItems: 1, optional: true}
    "cold", 
    "ice"
  ],
  "dimensions": {    // {optional: true}
    "length": 7.0,
    "width": 12.0,
    "height": 9.5
  }
}

The JSight Schema language is especially useful when describing nested objects and arrays, which are very common in real life. You simply give an example of a valid array or object, and add small clarifying comments.

It is much more complicated in JSON Schema and other languages.

For details, see the JSight Schema Language Specification, sections:

Star us on GitHub — it motivates us a lot!

{
  "type": "object",
  "properties": {
    "productId": {
      "type": "integer"
    },
    "productName": {
      "type": "string"
    },
    "price": {
      "type": "number",
      "exclusiveMinimum": 0
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1
    },
    "dimensions": {
      "type": "object",
      "properties": {
        "length": {
          "type": "number"
        },
        "width": {
          "type": "number"
        },
        "height": {
          "type": "number"
        }
      },
      "required": [ "length", "width", "height" ]
    }
  },
  "required": ["productId","productName","price"],
  "examples": [{
    "productId": 1,
    "productName": "An ice sculpture",
    "price": 12.50,
    "tags": [ "cold", "ice" ],
    "dimensions": {
      "length": 7.0,
      "width": 12.0,
      "height": 9.5
    }
  }]
}

This example was created based on the official Getting Started instructions of the JSON-Schema standard.

Example 3. Property description
JSight Schema 0.3 JSON Schema 2020-12
{ // A product from Acme's catalog.
  "productId": 1,                    // The unique id.
  "productName": "An ice sculpture", // Name of the product.
  
  "price": 12.50, /* {
                       min: 0, 
                       exclusiveMinimum: true
                     } 
                     - The price. */

  "tags": [   /* {minItems: 1, optional: true}    
                 - Tags for the product. */
    "cold", 
    "ice"
  ],
  "dimensions": { // {optional: true} - The dimensions.
    "length": 7.0,
    "width": 12.0,
    "height": 9.5
  }
}

Here is the same schema as in the previous example, only property descriptions have been added.

Property descriptions are written in C-like comments. If there are rules in the comments, then the property descriptions are separated by a hyphen.

For details, see the JSight Schema Language Specification, section “Text notes to RULES”.

Star us on GitHub — it motivates us a lot!

{
  "type": "object",
  "description": "A product from Acme's catalog.",
  "properties": {
    "productId": {
      "description": "The unique id.",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product.",
      "type": "string"
    },
    "price": {
      "description": "The price.",
      "type": "number",
      "exclusiveMinimum": 0
    },
    "tags": {
      "description": "Tags for the product.",
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1
    },
    "dimensions": {
      "description": "The dimensions.",
      "type": "object",
      "properties": {
        "length": {
          "type": "number"
        },
        "width": {
          "type": "number"
        },
        "height": {
          "type": "number"
        }
      },
      "required": ["length", "width", "height"]
    }
  },
  "required": ["productId","productName","price"],
  "examples": [{
    "productId": 1,
    "productName": "An ice sculpture",
    "price": 12.50,
    "tags": [ "cold", "ice" ],
    "dimensions": {
      "length": 7.0,
      "width": 12.0,
      "height": 9.5
    }
  }]
}
Example 4. Built-in data types
JSight Schema 0.3 JSON Schema 2020-12
{
  "id"        : 123,
  "name"      : "Tom",
  "email"     : "tom@cats.com",              // {type: "email"   }
  "website"   : "http://tom.cats.com",       // {type: "uri"     }
  "birthday"  : "2006-01-02",                // {type: "date"    }
  "registered": "2021-01-02T07:23:12+03:00", // {type: "datetime"}
  "uuid": "550e8400-e29b-41d4-a716-446655440000" // {type: "uuid"}
}

JSight Schema supports several additional built-in data types that are required for actual work.

Read more about built-in data types in the JSight Schema Language Specification, section “RULE "type"”.

Star us on GitHub — it motivates us a lot!

{
  "type": "object",
  "properties": {
    "id": {
      "type": "integer",
      "examples": [123]
    },
    "name": {
      "type": "string",
      "examples": ["Tom"]
    },
    "email": {
      "type": "string",
      "format": "email",
      "examples": ["tom@cats.com"]
    },
    "website": {
      "type": "string",
      "format": "uri",
      "examples": ["http://tom.cats.com"]
    },
    "birthday": {
      "type": "string",
      "format": "date",
      "examples": ["2006-01-02"]
    },
    "registered": {
      "type": "string",
      "format": "date-time",
      "examples": ["2021-01-02T07:23:12+03:00"]
    },
    "uuid": {
      "type": "string",
      "format": "uuid",
      "examples": [
        "550e8400-e29b-41d4-a716-446655440000"
      ]
    }
  },
  "required": [
    "id",
    "name",
    "email",
    "website",
    "birthday",
    "registered",
    "uuid"
  ]
}
 

📑   Versioning

JSight Schema Go Library releases are versioned according to the Semantic Versioning 2.0.0 standard.

{MAJOR version}.{MINOR version}.{PATCH version}

Releases are located in the branch main, and are tagged with a version number, for example, v1.0.0.

The JSight Schema Go Library release history can be seen here: https://github.com/jsightapi/jsight-schema-core/releases.

 

📔   Dependencies

JSight Schema Go Library dependencies are described in the file go.mod.

 

🧪   Tests

To run automated tests, run the following command in the repository root folder:

go test -cover ./...
 

😎   Contributing

Contributing is more than just coding. You can help the project in many ways, and we will be very happy to accept your contribution to our project.

Details of how you can help the project are described in the CONTRIBUTING.md document.

 
Contributors

 

💬   Bugs and Feature Requests

Do you have a bug report or a feature request?

Please feel free to add a new issue or write to us in support:

 

❔   Support

If something is unclear to you, please contact support; we try to respond within 24 hours. Moreover, it is critical for us to understand what is unclear from the first instance.

 

🧾   License

This project is licensed under the Apache 2.0 License. See the LICENSE file for more details.

 

📖   Resources

Documents:
Applications that use the JSight Schema Go Library:
Publications:
Others:
 

🤝   Partners

 

🏆   Acknowledgments

We sincerely thank all those without whom this project would not have been possible:

Star us on GitHub — it motivates us a lot!

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsValidType

func IsValidType(s string) bool

Types

type ASTNode

type ASTNode struct {
	// TokenType corresponding JSON type for this AST node's value.
	TokenType TokenType

	// SchemaType corresponding schema type for this AST node's value.
	SchemaType string

	// Key a node key (if this is the property of the object).
	Key string

	// Value a node value.
	// Make sense only for scalars and shortcuts.
	Value string

	// Comment a ast node comment.
	Comment string

	// Rules a map of attached rules.
	Rules *RuleASTNodes

	// Children contains all array items and object properties.
	// Make sense only for arrays and object.
	Children []ASTNode

	// IsKeyShortcut will be true if this property key is shortcut.
	// Make sense only for AST nodes which are represents object property.
	IsKeyShortcut bool

	// InheritedFrom a user type from which this property is inherited.
	InheritedFrom string
}

ASTNode an AST node.

func (*ASTNode) ObjectProperty

func (c *ASTNode) ObjectProperty(k string) *ASTNode

func (*ASTNode) Unshift

func (c *ASTNode) Unshift(n ASTNode)

type ASTNodes

type ASTNodes struct {
	// contains filtered or unexported fields
}

ASTNodes an ordered map of AST nodes. gen:OrderedMap

func (*ASTNodes) Delete

func (m *ASTNodes) Delete(k string)

func (*ASTNodes) Each

func (m *ASTNodes) Each(fn eachASTNodesFunc) error

func (*ASTNodes) EachSafe

func (m *ASTNodes) EachSafe(fn eachSafeASTNodesFunc)

func (*ASTNodes) Filter

func (m *ASTNodes) Filter(fn filterASTNodesFunc)

Filter iterates and changes values in the map.

func (*ASTNodes) Find

func (m *ASTNodes) Find(fn findASTNodesFunc) (ASTNodesItem, bool)

Find finds first matched item from the map.

func (*ASTNodes) Get

func (m *ASTNodes) Get(k string) (ASTNode, bool)

Get gets a value by key.

func (*ASTNodes) GetValue

func (m *ASTNodes) GetValue(k string) ASTNode

GetValue gets a value by key.

func (*ASTNodes) Has

func (m *ASTNodes) Has(k string) bool

Has checks that specified key is set.

func (*ASTNodes) Len

func (m *ASTNodes) Len() int

Len returns count of values.

func (*ASTNodes) Map

func (m *ASTNodes) Map(fn mapASTNodesFunc) error

Map iterates and changes values in the map.

func (*ASTNodes) MarshalJSON

func (m *ASTNodes) MarshalJSON() ([]byte, error)

func (*ASTNodes) Set

func (m *ASTNodes) Set(k string, v ASTNode)

Set sets a value with specified key.

func (*ASTNodes) Update

func (m *ASTNodes) Update(k string, fn func(v ASTNode) ASTNode)

Update updates a value with specified key.

type ASTNodesItem

type ASTNodesItem struct {
	Key   string
	Value ASTNode
}

ASTNodesItem represent single data from the ASTNodes.

type Document

type Document interface {
	// NextLexeme returns next lexeme from this document.
	// Might return ParsingError if document isn't valid.
	// Will return io.EOF when no more lexemes are available.
	NextLexeme() (lexeme.LexEvent, error)

	// Len returns length of document in bytes.
	// Might return ParsingError if document isn't valid.
	Len() (uint, error)

	// Check checks that this document is valid.
	// Can return ParsingError if document isn't valid.
	Check() error

	// Content returns the entire contents of the document
	Content() bytes.Bytes
}

Document represents a document. It's a concrete data. Data maybe a scalar type or complex type.

Not a thead safe!

Example of the valid documents: - "foo" - [1, 2, 3] - {"foo": "bar"}

type Rule

type Rule interface {
	// Len returns length of this rule in bytes.
	// Might return ParsingError if rule isn't valid.
	Len() (uint, error)

	// Check checks this rule is valid.
	// Can return ParsingError if rule isn't valid.
	Check() error

	// GetAST returns a root AST node for this schema.
	GetAST() (ASTNode, error)
}

Rule represents a custom user-defined rule.

type RuleASTNode

type RuleASTNode struct {
	// TokenType corresponding JSON type for this AST node's value.
	TokenType TokenType

	// Value a node value.
	// Make sense only for scalars and shortcuts.
	Value string

	// Comment a ast node comment.
	Comment string

	// Properties contains all object properties.
	// Make sense only for objects.
	Properties *RuleASTNodes

	// Items contains all array items.
	// Make sense only for arrays.
	Items []RuleASTNode

	// Source a source of this rule.
	Source RuleASTNodeSource
}

type RuleASTNodeSource

type RuleASTNodeSource int
const (
	RuleASTNodeSourceUnknown RuleASTNodeSource = iota

	// RuleASTNodeSourceManual indicates rule added manually by the user.
	RuleASTNodeSourceManual

	// RuleASTNodeSourceGenerated indicates rule generated inside the code.
	RuleASTNodeSourceGenerated
)

type RuleASTNodes

type RuleASTNodes struct {
	// contains filtered or unexported fields
}

RuleASTNodes an ordered map of rule AST nodes. gen:OrderedMap

func MakeRuleASTNodes

func MakeRuleASTNodes(capacity int) *RuleASTNodes

func NewRuleASTNodes

func NewRuleASTNodes(data map[string]RuleASTNode, order []string) *RuleASTNodes

func (*RuleASTNodes) Delete

func (m *RuleASTNodes) Delete(k string)

func (*RuleASTNodes) Each

func (m *RuleASTNodes) Each(fn eachRuleASTNodesFunc) error

func (*RuleASTNodes) EachSafe

func (m *RuleASTNodes) EachSafe(fn eachSafeRuleASTNodesFunc)

func (*RuleASTNodes) Filter

func (m *RuleASTNodes) Filter(fn filterRuleASTNodesFunc)

Filter iterates and changes values in the map.

func (*RuleASTNodes) Find

func (m *RuleASTNodes) Find(fn findRuleASTNodesFunc) (RuleASTNodesItem, bool)

Find finds first matched item from the map.

func (*RuleASTNodes) Get

func (m *RuleASTNodes) Get(k string) (RuleASTNode, bool)

Get gets a value by key.

func (*RuleASTNodes) GetValue

func (m *RuleASTNodes) GetValue(k string) RuleASTNode

GetValue gets a value by key.

func (*RuleASTNodes) Has

func (m *RuleASTNodes) Has(k string) bool

Has checks that specified key is set.

func (*RuleASTNodes) Len

func (m *RuleASTNodes) Len() int

Len returns count of values.

func (*RuleASTNodes) Map

func (m *RuleASTNodes) Map(fn mapRuleASTNodesFunc) error

Map iterates and changes values in the map.

func (*RuleASTNodes) MarshalJSON

func (m *RuleASTNodes) MarshalJSON() ([]byte, error)

func (*RuleASTNodes) Set

func (m *RuleASTNodes) Set(k string, v RuleASTNode)

Set sets a value with specified key.

func (*RuleASTNodes) Update

func (m *RuleASTNodes) Update(k string, fn func(v RuleASTNode) RuleASTNode)

Update updates a value with specified key.

type RuleASTNodesItem

type RuleASTNodesItem struct {
	Key   string
	Value RuleASTNode
}

RuleASTNodesItem represent single data from the RuleASTNodes.

type Schema

type Schema interface {
	// Len returns length of this schema in bytes.
	// Might return ParsingError if schema isn't valid.
	Len() (uint, error)

	// Example returns an example for this schema.
	// Might return ParsingError if schema isn't valid.
	Example() ([]byte, error)

	// AddType adds a new type to this schema.
	// Might return a ParsingError if add type isn't valid.
	AddType(name string, schema Schema) error

	// AddRule adds a new type to this schema.
	// Might return a ParsingError if add type isn't valid.
	AddRule(name string, schema Rule) error

	// Check checks that this schema is valid.
	// Can return ParsingError if schema isn't valid.
	Check() error

	// GetAST returns a root AST node for this schema.
	GetAST() (ASTNode, error)

	// UsedUserTypes return all used user types.
	UsedUserTypes() ([]string, error)
}

Schema represents a schema. Schema is a some description of expected structure of payload.

type SchemaType

type SchemaType string
const (
	SchemaTypeUndefined SchemaType = ""
	SchemaTypeString    SchemaType = "string"
	SchemaTypeInteger   SchemaType = "integer"
	SchemaTypeFloat     SchemaType = "float"
	SchemaTypeDecimal   SchemaType = "decimal"
	SchemaTypeBoolean   SchemaType = "boolean"
	SchemaTypeObject    SchemaType = "object"
	SchemaTypeArray     SchemaType = "array"
	SchemaTypeNull      SchemaType = "null"
	SchemaTypeEmail     SchemaType = "email"
	SchemaTypeURI       SchemaType = "uri"
	SchemaTypeUUID      SchemaType = "uuid"
	SchemaTypeDate      SchemaType = "date"
	SchemaTypeDateTime  SchemaType = "datetime"
	SchemaTypeEnum      SchemaType = "enum"
	SchemaTypeMixed     SchemaType = "mixed"
	SchemaTypeAny       SchemaType = "any"
	SchemaTypeComment   SchemaType = "comment"
)

func GuessSchemaType

func GuessSchemaType(b []byte) (SchemaType, error)

func (SchemaType) IsEqualSoft

func (t SchemaType) IsEqualSoft(x SchemaType) bool

IsEqualSoft compare two types with next assumptions% - Decimal is the same as float; - Email, URI, UUID, Date, and DateTime are the same as string; - Enum, Mixed and Any are the same as any other type.

func (SchemaType) IsOneOf

func (t SchemaType) IsOneOf(tt ...SchemaType) bool

IsOneOf return true if current schema is one of specified.

func (SchemaType) IsScalar

func (t SchemaType) IsScalar() bool

func (SchemaType) ToTokenType

func (t SchemaType) ToTokenType() string

type TokenType

type TokenType = string
const (
	TokenTypeNumber   TokenType = "number"
	TokenTypeString   TokenType = "string"
	TokenTypeBoolean  TokenType = "boolean"
	TokenTypeArray    TokenType = "array"
	TokenTypeObject   TokenType = "object"
	TokenTypeShortcut TokenType = "reference"
	TokenTypeNull     TokenType = "null"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL