jschema

package module
v0.9.3 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2023 License: MIT Imports: 12 Imported by: 2

README

Overview

A lib to convert existing golang struct into json schema list.

Features:

  • No need to modify the existing struct
  • Support anyOf for interface typing
  • Support custom type hijack
  • Support easy modification of the generated schema
  • Support enum type

Usage

Read example for more details.

Documentation

Overview

Package jschema ...

Example (Custom_handler)
package main

import (
	"fmt"
	"time"

	"github.com/NaturalSelectionLabs/jschema"
)

func main() {
	s := jschema.New("")

	s.Hijack(time.Time{}, func(scm *jschema.Schema) {
		// If we don't this the time will be a struct
		scm.Type = jschema.TypeString
		scm.AdditionalProperties = nil
	})

	type Data struct {
		Time time.Time `json:"time"`
	}

	s.Define(Data{})

	fmt.Println(s.String())

}
Output:

{
  "Data": {
    "title": "Data",
    "description": "github.com/NaturalSelectionLabs/jschema_test.Data",
    "type": "object",
    "properties": {
      "time": {
        "$ref": "#/$defs/Time"
      }
    },
    "required": [
      "time"
    ],
    "additionalProperties": false
  },
  "Time": {
    "title": "Time",
    "description": "time.Time",
    "type": "string"
  }
}

Index

Examples

Constants

View Source
const JTagItemPrefix = "item-"

Variables

This section is empty.

Functions

func SortJVal added in v0.7.15

func SortJVal(list []JVal)

Types

type Enum added in v0.6.0

type Enum interface {
	json.Marshaler
	json.Unmarshaler
	// Values returns all the possible raw json strings of the enum.
	Values() []json.RawMessage
}

type EnumString added in v0.6.0

type EnumString interface {
	json.Marshaler
	json.Unmarshaler
	Values() []string
}

type Hijack added in v0.9.0

type Hijack func(scm *Schema)

Hijack is the custom handler for a special type. scm is the parsed schema without this handler, modify it to produce the final schema.

type JTag added in v0.7.16

type JTag string
const (
	JTagDescription JTag = "description"
	JTagFormat      JTag = "format"
	JTagDefault     JTag = "default"
	JTagExamples    JTag = "examples"
	JTagPattern     JTag = "pattern"
	JTagMin         JTag = "min"
	JTagMax         JTag = "max"
	JTagMinLen      JTag = "minLen"
	JTagMaxLen      JTag = "maxLen"
	JTagMinItems    JTag = "minItems"
	JTagMaxItems    JTag = "maxItems"
)

func (JTag) String added in v0.7.16

func (t JTag) String() string

type JVal

type JVal interface{}

JVal can be any valid json value, e.g. string, number, bool, null, []interface{}, map[string]interface{}.

func ToJValList

func ToJValList[T any](list ...T) []JVal

type Properties

type Properties map[string]*Schema

type Ref

type Ref struct {
	Defs    string
	Package string
	Name    string
	Hash    string
	ID      string
}

func (Ref) MarshalJSON

func (r Ref) MarshalJSON() ([]byte, error)

func (Ref) String

func (r Ref) String() string

func (Ref) Unique

func (r Ref) Unique() bool

type Required added in v0.7.4

type Required []string

func (*Required) Add added in v0.7.4

func (r *Required) Add(names ...string)

Add names to the list if they are not in the list.

func (*Required) Has added in v0.7.4

func (r *Required) Has(name string) bool

type Schema

type Schema struct {
	Title       string `json:"title,omitempty"`
	Description string `json:"description,omitempty"`
	Default     JVal   `json:"default,omitempty"`
	Examples    []JVal `json:"examples,omitempty"`

	// Any type validation
	AnyOf             []*Schema  `json:"anyOf,omitempty"`
	Ref               *Ref       `json:"$ref,omitempty"`
	Type              SchemaType `json:"type,omitempty"` // string, number, boolean, null, array, object
	Enum              []JVal     `json:"enum,omitempty"`
	Properties        Properties `json:"properties,omitempty"`
	PatternProperties Properties `json:"patternProperties,omitempty"`
	Format            string     `json:"format,omitempty"`

	// Number validation
	Max *float64 `json:"maximum,omitempty"`
	Min *float64 `json:"minimum,omitempty"`

	// String validation
	MaxLen  *float64 `json:"maxLength,omitempty"`
	MinLen  *float64 `json:"minLength,omitempty"`
	Pattern string   `json:"pattern,omitempty"`

	// Array validation
	Items    *Schema `json:"items,omitempty"`
	MinItems *int    `json:"minItems,omitempty"`
	MaxItems *int    `json:"maxItems,omitempty"`

	// Object validation
	Required             Required `json:"required,omitempty"`
	AdditionalProperties *bool    `json:"additionalProperties,omitempty"`

	Defs Types `json:"$defs,omitempty"`
}

Schema is designed for typescript conversion. Its fields is a strict subset of json schema fields.

func (*Schema) ChangeDefs added in v0.7.7

func (s *Schema) ChangeDefs(to string)

func (*Schema) Clone

func (s *Schema) Clone() *Schema

func (*Schema) String added in v0.7.5

func (s *Schema) String() string

type SchemaType

type SchemaType string
const (
	TypeString  SchemaType = "string"
	TypeNumber  SchemaType = "number"
	TypeInteger SchemaType = "integer"
	TypeObject  SchemaType = "object"
	TypeArray   SchemaType = "array"
	TypeBool    SchemaType = "boolean"
	TypeNull    SchemaType = "null"
	TypeUnknown SchemaType = "unknown"
)

type Schemas

type Schemas struct {
	// contains filtered or unexported fields
}
Example
package main

import (
	"fmt"

	"github.com/NaturalSelectionLabs/jschema"
	"github.com/NaturalSelectionLabs/jschema/lib/test"
	"github.com/naturalselectionlabs/vary"
)

func main() {
	// Create a schema list instance
	schemas := jschema.New("#/components/schemas")

	type Metadata interface{}

	// Make the metadata field accept either A or B
	iMetadata := vary.New(new(Metadata))

	type A string

	iMetadata.Add(A(""))

	type B int

	iMetadata.Add(B(0))

	type Node struct {
		// Use the pattern or format tag to set the standard json schema validation rule
		Name     string   `json:"name" pattern:"^[a-z]+$" format:"name"`
		Metadata Metadata `json:"metadata,omitempty"` // omitempty make this field optional
		Version  string   `json:"version"`
		// jschema supports github.com/dmarkham/enumer generated enum
		// The enum type must implements [jschema.Enum] or [jschema.EnumString].
		// Otherwise, it will be treated as a normal type.
		Enum test.Enum `json:"enum"`
	}

	schemas.Define(Node{})
	node := schemas.PeakSchema(Node{})

	// Define default value
	{
		node.Properties["name"].Default = "jack"
	}

	// Define constants
	{
		node.Properties["version"] = schemas.Const("v1")
	}

	fmt.Println(schemas.String())

}
Output:

{
  "A": {
    "title": "A",
    "description": "github.com/NaturalSelectionLabs/jschema_test.A",
    "type": "string"
  },
  "B": {
    "title": "B",
    "description": "github.com/NaturalSelectionLabs/jschema_test.B",
    "type": "integer"
  },
  "Enum": {
    "title": "Enum",
    "description": "github.com/NaturalSelectionLabs/jschema/lib/test.Enum",
    "enum": [
      "one",
      "three",
      "two"
    ]
  },
  "Metadata": {
    "title": "Metadata",
    "description": "github.com/NaturalSelectionLabs/jschema_test.Metadata",
    "anyOf": [
      {
        "$ref": "#/components/schemas/A"
      },
      {
        "$ref": "#/components/schemas/B"
      }
    ]
  },
  "Node": {
    "title": "Node",
    "description": "github.com/NaturalSelectionLabs/jschema_test.Node",
    "type": "object",
    "properties": {
      "enum": {
        "$ref": "#/components/schemas/Enum"
      },
      "metadata": {
        "$ref": "#/components/schemas/Metadata"
      },
      "name": {
        "default": "jack",
        "type": "string",
        "format": "name",
        "pattern": "^[a-z]+$"
      },
      "version": {
        "type": "string",
        "enum": [
          "v1"
        ]
      }
    },
    "required": [
      "name",
      "version",
      "enum"
    ],
    "additionalProperties": false
  }
}

func New

func New(refPrefix string) Schemas

New Schemas instance. The defs is the prefix used for each $ref path. Such as if you set defs to "#/components/schemas", then a $ref may looks like "#/components/schemas/Node".

Example
package main

import (
	"fmt"

	"github.com/NaturalSelectionLabs/jschema"
)

func main() {
	type Node struct {
		// Use tags like default, examples to set the json schema validation rules.
		ID int `json:"id" default:"1" examples:"[1,2,3]" min:"0" max:"100"`

		// Use the tags to set description, min, max, etc. All available tags are [jschema.JTag].
		// Use [jschema.JTagItemPrefix] to prefix [jschema.JTag] to set the array item.
		Children []*Node `json:"children" description:"The children of the node" minItems:"0" maxItems:"10"`
	}

	// Create a schema list instance
	schemas := jschema.New("#/components/schemas")

	// Define a type within the schema
	schemas.Define(Node{})
	schemas.Description(Node{}, "A node in the tree")

	fmt.Println(schemas.String())

}
Output:

{
  "Node": {
    "title": "Node",
    "description": "A node in the tree",
    "type": "object",
    "properties": {
      "children": {
        "description": "The children of the node",
        "type": "array",
        "items": {
          "anyOf": [
            {
              "$ref": "#/components/schemas/Node"
            },
            {
              "type": "null"
            }
          ]
        },
        "minItems": 0,
        "maxItems": 10
      },
      "id": {
        "default": 1,
        "examples": [
          1,
          2,
          3
        ],
        "type": "integer",
        "maximum": 100,
        "minimum": 0
      }
    },
    "required": [
      "id",
      "children"
    ],
    "additionalProperties": false
  }
}

func NewWithInterfaces added in v0.3.0

func NewWithInterfaces(refPrefix string, interfaces vary.Interfaces) Schemas

func (*Schemas) AnyOf

func (s *Schemas) AnyOf(list ...interface{}) *Schema

func (*Schemas) Const

func (s *Schemas) Const(v JVal) *Schema

func (Schemas) Define

func (s Schemas) Define(v interface{}) *Schema

Define is a shortcut for Schemas.DefineT.

func (Schemas) DefineFieldT added in v0.7.4

func (s Schemas) DefineFieldT(f reflect.StructField) *Schema

func (Schemas) DefineT

func (s Schemas) DefineT(t reflect.Type) *Schema

DefineT converts the t to Schema recursively and append newly meet schemas to the schema list s.

func (Schemas) Description added in v0.1.0

func (s Schemas) Description(v interface{}, desc string)

Description set the description for current type.

func (Schemas) Hijack added in v0.9.0

func (s Schemas) Hijack(v interface{}, h Hijack)

func (Schemas) HijackBigInt added in v0.9.0

func (s Schemas) HijackBigInt()

func (Schemas) HijackJSONRawMessage added in v0.9.0

func (s Schemas) HijackJSONRawMessage()

func (Schemas) HijackTime added in v0.9.0

func (s Schemas) HijackTime()

func (Schemas) JSON

func (s Schemas) JSON() map[string]*Schema

JSON returns a JSON representation of the schemas. Usually you json.Marshal it to generate a json file.

func (*Schemas) PeakSchema added in v0.0.3

func (s *Schemas) PeakSchema(v interface{}) *Schema

PeakSchema returns the schema for the given target it won't modify the schema list. If the target is a schema it will auto expand the ref and return the schema itself.

func (*Schemas) Ref

func (s *Schemas) Ref(v interface{}) Ref

func (*Schemas) RefT

func (s *Schemas) RefT(t reflect.Type) Ref

func (*Schemas) SchemaT added in v0.7.5

func (s *Schemas) SchemaT(t reflect.Type) *Schema

SchemaT returns a standalone schema for the given type.

func (*Schemas) SetSchema

func (s *Schemas) SetSchema(target interface{}, v *Schema)

SetSchema sets the schema for the given target. It will keep the title and description.

func (Schemas) String added in v0.1.0

func (s Schemas) String() string

String returns a json string representation of the schemas.

func (*Schemas) ToStandAlone added in v0.7.6

func (s *Schemas) ToStandAlone(scm *Schema) *Schema

type Tag

type Tag struct {
	Name      string
	Ignore    bool
	Omitempty bool
	String    bool
}

func ParseJSONTag

func ParseJSONTag(st reflect.StructTag) *Tag

type Types

type Types map[string]*Schema

Directories

Path Synopsis
lib
test
Package test ...
Package test ...

Jump to

Keyboard shortcuts

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