jsonschema

package module
v0.11.2 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2023 License: MIT Imports: 19 Imported by: 3

README

copy 适应自己的项目 加入自定义schema定义

  • 新增 Intercept 函数 可以传入拦截生成 返回false则不会生成Schema
    • 用于比如新增时或修改时 跳过某些字段的生成
  • 新增 OpenMetaData bool 注入meta数据 目前用于标记数字的精确类型
    • 会额外生成一个meta_data{kind:准确golang kind 字符串}的map
    • 当然了 你也可以手动设置 MetaData注入你想要注入的其他内容
  • 新增 TagMapper map[string]TagMapperFunc 用来自定义tag映射
    • 快捷方法 AddTagSetMapper 用来处理简单的tag赋值
      • 例如指定tag为 comment 赋值的字段为 Title 则会把Title的值赋值为 comment标签设定的内容
      • comment="someLike" 最终会设置schema的Title为 someLike
      • 是字段名 大写开头
    • 通用方法 AddTagMapper 自定义设置tag以及对应的处理方法函数
  • 新增 Modifier 方法 可以在最后自定义变更schema的任何数据
    • 自由且强大 几乎适配所有情况

Documentation

Overview

Package jsonschema uses reflection to generate JSON Schemas from Go types [1].

If json tags are present on struct fields, they will be used to infer property names and if a property is required (omitempty is present).

[1] http://json-schema.org/latest/json-schema-validation.html

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// TrueSchema defines a schema with a true value
	TrueSchema = &Schema{boolean: &[]bool{true}[0]}
	// FalseSchema defines a schema with a false value
	FalseSchema = &Schema{boolean: &[]bool{false}[0]}
)
View Source
var Version = "https://json-schema.org/draft/2020-12/schema"

Version is the JSON Schema version.

Functions

func ExtractGoComments

func ExtractGoComments(base, path string, commentMap map[string]string) error

ExtractGoComments will read all the go files contained in the provided path, including sub-directories, in order to generate a dictionary of comments associated with Types and Fields. The results will be added to the `commentsMap` provided in the parameters and expected to be used for Schema "description" fields.

The `go/parser` library is used to extract all the comments and unfortunately doesn't have a built-in way to determine the fully qualified name of a package. The `base` paremeter, the URL used to import that package, is thus required to be able to match reflected types.

When parsing type comments, we use the `go/doc`'s Synopsis method to extract the first phrase only. Field comments, which tend to be much shorter, will include everything.

func FindDataByAccessKey added in v0.11.0

func FindDataByAccessKey(data interface{}, accessKey string) interface{}

func GetSchemaMapByPointer added in v0.11.0

func GetSchemaMapByPointer(schema map[string]interface{}, pointer string) (map[string]interface{}, error)

GetSchemaMapByPointer 传入一个被序列化之后的 json schema , 和对应需要获取的pointer , 返回 获取到的schema 或者 error pointer 格式为 /字段1/字段2 或者 #/字段1/字段2

func MapToStruct added in v0.11.0

func MapToStruct[T any](m map[string]any, out T) error

func StructToMap added in v0.11.0

func StructToMap(in any) (map[string]any, error)

StructToMap 通过json序列化实现struct到map

func ToSnakeCase

func ToSnakeCase(str string) string

ToSnakeCase converts the provided string into snake case using dashes. This is useful for Schema IDs and definitions to be coherent with common JSON Schema examples.

Types

type Definitions

type Definitions map[string]*Schema

Definitions hold schema definitions. http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.26 RFC draft-wright-json-schema-validation-00, section 5.26

type ID

type ID string

ID represents a Schema ID type which should always be a URI. See draft-bhutton-json-schema-00 section 8.2.1

const EmptyID ID = ""

EmptyID is used to explicitly define an ID with no value.

func (ID) Add

func (id ID) Add(path string) ID

Add appends the provided path to the id, and removes any anchor data that might be there.

func (ID) Anchor

func (id ID) Anchor(name string) ID

Anchor sets the anchor part of the schema URI.

func (ID) Base

func (id ID) Base() ID

Base removes any anchor information from the schema

func (ID) Def

func (id ID) Def(name string) ID

Def adds or replaces a definition identifier.

func (ID) String

func (id ID) String() string

String provides string version of ID

func (ID) Validate

func (id ID) Validate() error

Validate is used to check if the ID looks like a proper schema. This is done by parsing the ID as a URL and checking it has all the relevant parts.

type Reflector

type Reflector struct {
	// BaseSchemaID defines the URI that will be used as a base to determine Schema
	// IDs for models. For example, a base Schema ID of `https://invopop.com/schemas`
	// when defined with a struct called `User{}`, will result in a schema with an
	// ID set to `https://invopop.com/schemas/user`.
	//
	// If no `BaseSchemaID` is provided, we'll take the type's complete package path
	// and use that as a base instead. Set `Anonymous` to try if you do not want to
	// include a schema ID.
	BaseSchemaID ID

	// Anonymous when true will hide the auto-generated Schema ID and provide what is
	// known as an "anonymous schema". As a rule, this is not recommended.
	Anonymous bool

	// AssignAnchor when true will use the original struct's name as an anchor inside
	// every definition, including the root schema. These can be useful for having a
	// reference to the original struct's name in CamelCase instead of the snake-case used
	// by default for URI compatibility.
	//
	// Anchors do not appear to be widely used out in the wild, so at this time the
	// anchors themselves will not be used inside generated schema.
	AssignAnchor bool

	// AllowAdditionalProperties will cause the Reflector to generate a schema
	// without additionalProperties set to 'false' for all struct types. This means
	// the presence of additional keys in JSON objects will not cause validation
	// to fail. Note said additional keys will simply be dropped when the
	// validated JSON is unmarshaled.
	AllowAdditionalProperties bool

	// RequiredFromJSONSchemaTags will cause the Reflector to generate a schema
	// that requires any key tagged with `jsonschema:required`, overriding the
	// default of requiring any key *not* tagged with `json:,omitempty`.
	RequiredFromJSONSchemaTags bool

	// Do not reference definitions. This will remove the top-level $defs map and
	// instead cause the entire structure of types to be output in one tree. The
	// list of type definitions (`$defs`) will not be included.
	DoNotReference bool

	// ExpandedStruct when true will include the reflected type's definition in the
	// root as opposed to a definition with a reference.
	ExpandedStruct bool

	// IgnoredTypes defines a slice of types that should be ignored in the schema,
	// switching to just allowing additional properties instead.
	IgnoredTypes []interface{}

	// Lookup allows a function to be defined that will provide a custom mapping of
	// types to Schema IDs. This allows existing schema documents to be referenced
	// by their ID instead of being embedded into the current schema definitions.
	// Reflected types will never be pointers, only underlying elements.
	Lookup func(reflect.Type) ID

	// Mapper is a function that can be used to map custom Go types to jsonschema schemas.
	Mapper func(reflect.Type) *Schema

	// Intercept 拦截器 可返回false拦截生成
	// 用例在于 传入同一个struct 不同的情况可能会跳过某些字段的生成 但又不能设置 json标签为-
	Intercept func(reflect.StructField) bool

	// Namer allows customizing of type names. The default is to use the type's name
	// provided by the reflect package.
	Namer func(reflect.Type) string

	// KeyNamer allows customizing of key names.
	// The default is to use the key's name as is, or the json tag if present.
	// If a json tag is present, KeyNamer will receive the tag's name as an argument, not the original key name.
	KeyNamer func(string) string

	// AdditionalFields allows adding structfields for a given type
	AdditionalFields func(reflect.Type) []reflect.StructField

	// CommentMap is a dictionary of fully qualified go types and fields to comment
	// strings that will be used if a description has not already been provided in
	// the tags. Types and fields are added to the package path using "." as a
	// separator.
	//
	// Type descriptions should be defined like:
	//
	//   map[string]string{"github.com/23233/jsonschema.Reflector": "A Reflector reflects values into a Schema."}
	//
	// And Fields defined as:
	//
	//   map[string]string{"github.com/23233/jsonschema.Reflector.DoNotReference": "Do not reference definitions."}
	//
	// See also: AddGoComments
	CommentMap map[string]string

	// TagMapper 自定义解析tag对应的处理函数
	TagMapper map[string]TagMapperFunc

	// DoNotBase64 禁用base64的判断 用于区分定义中的 []uint8和 []byte相同的窘境
	DoNotBase64 bool

	// Modifier 修改器可以修改最后生成的schema
	// fieldName 是会在parent的 Properties中 新增的key名称
	Modifier func(now *Schema, structField reflect.StructField, parent *Schema, parentType reflect.Type, fieldName string)
}

A Reflector reflects values into a Schema.

func (*Reflector) AddGoComments

func (r *Reflector) AddGoComments(base, path string) error

AddGoComments will update the reflectors comment map with all the comments found in the provided source directories. See the #ExtractGoComments method for more details.

func (*Reflector) AddTagMapper added in v0.6.0

func (r *Reflector) AddTagMapper(tagName string, call TagMapperFunc)

func (*Reflector) AddTagSetExtraMapper added in v0.9.0

func (r *Reflector) AddTagSetExtraMapper(tagName string, kvSep string)

AddTagSetExtraMapper 设置到extra中 仅在序列化时输出的字段数据 默认多个元素之间的分隔符号为 , 号 kv分隔符不能为,号 且必须提供 sep 默认是不报错的 分割符一定要正确 eg: extras="field1:abcd,fields2:dbdb" 会附加后成 Extras:{"field1":"abcd","fields2":"dbdb"}

func (*Reflector) AddTagSetMapper added in v0.6.0

func (r *Reflector) AddTagSetMapper(tagName string, fieldName string)

AddTagSetMapper 新增标签赋值mapper eg: comment="someLike" 设置tagName为comment 设置fieldName为schema中的Title字段 会使用反射进行赋值 最终会设置schema的Title为 someLike 可能的问题 对于struct和slice并未支持 需要自己处理

func (*Reflector) Reflect

func (r *Reflector) Reflect(v interface{}) *Schema

Reflect reflects to Schema from a value.

func (*Reflector) ReflectFromType

func (r *Reflector) ReflectFromType(t reflect.Type) *Schema

ReflectFromType generates root schema

func (*Reflector) SetBaseSchemaID

func (r *Reflector) SetBaseSchemaID(id string)

SetBaseSchemaID is a helper use to be able to set the reflectors base schema ID from a string as opposed to then ID instance.

type Schema

type Schema struct {
	// RFC draft-bhutton-json-schema-00
	Version     string      `json:"$schema,omitempty" bson:"version,omitempty"`         // section 8.1.1
	ID          ID          `json:"$id,omitempty" bson:"id,omitempty"`                  // section 8.2.1
	Anchor      string      `json:"$anchor,omitempty" bson:"anchor,omitempty"`          // section 8.2.2
	Ref         string      `json:"$ref,omitempty" bson:"ref,omitempty"`                // section 8.2.3.1
	DynamicRef  string      `json:"$dynamicRef,omitempty" bson:"dynamic_ref,omitempty"` // section 8.2.3.2
	Definitions Definitions `json:"$defs,omitempty" bson:"definitions,omitempty"`       // section 8.2.4
	Comments    string      `json:"$comment,omitempty" bson:"comments,omitempty"`       // section 8.3
	// RFC draft-bhutton-json-schema-00 section 10.2.1 (Sub-schemas with logic)
	AllOf []*Schema `json:"allOf,omitempty" bson:"all_of,omitempty"` // section 10.2.1.1
	AnyOf []*Schema `json:"anyOf,omitempty" bson:"any_of,omitempty"` // section 10.2.1.2
	OneOf []*Schema `json:"oneOf,omitempty" bson:"one_of,omitempty"` // section 10.2.1.3
	Not   *Schema   `json:"not,omitempty" bson:"not,omitempty"`      // section 10.2.1.4
	// RFC draft-bhutton-json-schema-00 section 10.2.2 (Apply sub-schemas conditionally)
	If               *Schema            `json:"if,omitempty" bson:"if,omitempty"`                              // section 10.2.2.1
	Then             *Schema            `json:"then,omitempty" bson:"then,omitempty"`                          // section 10.2.2.2
	Else             *Schema            `json:"else,omitempty" bson:"else,omitempty"`                          // section 10.2.2.3
	DependentSchemas map[string]*Schema `json:"dependentSchemas,omitempty" bson:"dependent_schemas,omitempty"` // section 10.2.2.4
	// RFC draft-bhutton-json-schema-00 section 10.3.1 (arrays)
	PrefixItems []*Schema `json:"prefixItems,omitempty" bson:"prefix_items,omitempty"` // section 10.3.1.1
	Items       *Schema   `json:"items,omitempty" bson:"items,omitempty"`              // section 10.3.1.2  (replaces additionalItems)
	Contains    *Schema   `json:"contains,omitempty" bson:"contains,omitempty"`        // section 10.3.1.3
	// RFC draft-bhutton-json-schema-00 section 10.3.2 (sub-schemas)
	Properties           *orderedmap.OrderedMap `json:"properties,omitempty" bson:"properties,omitempty"`                      // section 10.3.2.1
	PatternProperties    map[string]*Schema     `json:"patternProperties,omitempty" bson:"pattern_properties,omitempty"`       // section 10.3.2.2
	AdditionalProperties *Schema                `json:"additionalProperties,omitempty" bson:"additional_properties,omitempty"` // section 10.3.2.3
	PropertyNames        *Schema                `json:"propertyNames,omitempty" bson:"property_names,omitempty"`               // section 10.3.2.4
	// RFC draft-bhutton-json-schema-validation-00, section 6
	Type              string              `json:"type,omitempty" bson:"type,omitempty"`                            // section 6.1.1
	Enum              []interface{}       `json:"enum,omitempty" bson:"enum,omitempty"`                            // section 6.1.2
	Const             interface{}         `json:"const,omitempty" bson:"const,omitempty"`                          // section 6.1.3
	MultipleOf        int                 `json:"multipleOf,omitempty" bson:"multiple_of,omitempty"`               // section 6.2.1
	Maximum           int                 `json:"maximum,omitempty" bson:"maximum,omitempty"`                      // section 6.2.2
	ExclusiveMaximum  bool                `json:"exclusiveMaximum,omitempty" bson:"exclusive_maximum,omitempty"`   // section 6.2.3
	Minimum           int                 `json:"minimum,omitempty" bson:"minimum,omitempty"`                      // section 6.2.4
	ExclusiveMinimum  bool                `json:"exclusiveMinimum,omitempty" bson:"exclusive_minimum,omitempty"`   // section 6.2.5
	MaxLength         int                 `json:"maxLength,omitempty" bson:"max_length,omitempty"`                 // section 6.3.1
	MinLength         int                 `json:"minLength,omitempty" bson:"min_length,omitempty"`                 // section 6.3.2
	Pattern           string              `json:"pattern,omitempty" bson:"pattern,omitempty"`                      // section 6.3.3
	MaxItems          int                 `json:"maxItems,omitempty" bson:"max_items,omitempty"`                   // section 6.4.1
	MinItems          int                 `json:"minItems,omitempty" bson:"min_items,omitempty"`                   // section 6.4.2
	UniqueItems       bool                `json:"uniqueItems,omitempty" bson:"unique_items,omitempty"`             // section 6.4.3
	MaxContains       uint                `json:"maxContains,omitempty" bson:"max_contains,omitempty"`             // section 6.4.4
	MinContains       uint                `json:"minContains,omitempty" bson:"min_contains,omitempty"`             // section 6.4.5
	MaxProperties     int                 `json:"maxProperties,omitempty" bson:"max_properties,omitempty"`         // section 6.5.1
	MinProperties     int                 `json:"minProperties,omitempty" bson:"min_properties,omitempty"`         // section 6.5.2
	Required          []string            `json:"required,omitempty" bson:"required,omitempty"`                    // section 6.5.3
	DependentRequired map[string][]string `json:"dependentRequired,omitempty" bson:"dependent_required,omitempty"` // section 6.5.4
	// RFC draft-bhutton-json-schema-validation-00, section 7
	Format string `json:"format,omitempty" bson:"format,omitempty"`
	// RFC draft-bhutton-json-schema-validation-00, section 8
	ContentEncoding  string  `json:"contentEncoding,omitempty" bson:"content_encoding,omitempty"`    // section 8.3
	ContentMediaType string  `json:"contentMediaType,omitempty" bson:"content_media_type,omitempty"` // section 8.4
	ContentSchema    *Schema `json:"contentSchema,omitempty" bson:"content_schema,omitempty"`        // section 8.5
	// RFC draft-bhutton-json-schema-validation-00, section 9
	Title       string        `json:"title,omitempty" bson:"title,omitempty"`             // section 9.1
	Description string        `json:"description,omitempty" bson:"description,omitempty"` // section 9.1
	Default     interface{}   `json:"default,omitempty" bson:"default,omitempty"`         // section 9.2
	Deprecated  bool          `json:"deprecated,omitempty" bson:"deprecated,omitempty"`   // section 9.3
	ReadOnly    bool          `json:"readOnly,omitempty" bson:"read_only,omitempty"`      // section 9.4
	WriteOnly   bool          `json:"writeOnly,omitempty" bson:"write_only,omitempty"`    // section 9.4
	Examples    []interface{} `json:"examples,omitempty" bson:"examples,omitempty"`       // section 9.5

	Extras map[string]interface{} `json:"-"`

	// 自定义ui部分 仅存储 不验证
	Widget string `json:"widget,omitempty" bson:"widget,omitempty"` // ui组件

	// 额外注入的内容
	MetaData map[string]interface{} `json:"meta_data,omitempty" bson:"meta_data,omitempty"`
	// contains filtered or unexported fields
}

Schema represents a JSON Schema object type. RFC draft-bhutton-json-schema-00 section 4.3

func NewSchema added in v0.2.0

func NewSchema(types ...string) *Schema

func NewSchemaSetItems added in v0.2.0

func NewSchemaSetItems(typeName string) *Schema

func Reflect

func Reflect(v interface{}) *Schema

Reflect reflects to Schema from a value using the default Reflector

Example
package main

import (
	"encoding/json"
	"fmt"
	"time"

	"github.com/23233/jsonschema"
)

type SampleUser struct {
	ID          int                    `json:"id"`
	Name        string                 `json:"name" jsonschema:"title=the name,description=The name of a friend,example=joe,example=lucy,default=alex"`
	Friends     []int                  `json:"friends,omitempty" jsonschema_description:"The list of IDs, omitted when empty"`
	Tags        map[string]interface{} `json:"tags,omitempty" jsonschema_extras:"a=b,foo=bar,foo=bar1"`
	BirthDate   time.Time              `json:"birth_date,omitempty" jsonschema:"oneof_required=date"`
	YearOfBirth string                 `json:"year_of_birth,omitempty" jsonschema:"oneof_required=year"`
	Metadata    interface{}            `json:"metadata,omitempty" jsonschema:"oneof_type=string;array"`
	FavColor    string                 `json:"fav_color,omitempty" jsonschema:"enum=red,enum=green,enum=blue"`
}

func main() {
	s := jsonschema.Reflect(&SampleUser{})
	data, err := json.MarshalIndent(s, "", "  ")
	if err != nil {
		panic(err.Error())
	}
	fmt.Println(string(data))
}
Output:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/23233/jsonschema_test/sample-user",
  "$ref": "#/$defs/SampleUser",
  "$defs": {
    "SampleUser": {
      "oneOf": [
        {
          "required": [
            "birth_date"
          ],
          "title": "date"
        },
        {
          "required": [
            "year_of_birth"
          ],
          "title": "year"
        }
      ],
      "properties": {
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string",
          "title": "the name",
          "description": "The name of a friend",
          "default": "alex",
          "examples": [
            "joe",
            "lucy"
          ]
        },
        "friends": {
          "items": {
            "type": "integer"
          },
          "type": "array",
          "description": "The list of IDs, omitted when empty"
        },
        "tags": {
          "type": "object",
          "a": "b",
          "foo": [
            "bar",
            "bar1"
          ]
        },
        "birth_date": {
          "type": "string",
          "format": "date-time"
        },
        "year_of_birth": {
          "type": "string"
        },
        "metadata": {
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "array"
            }
          ]
        },
        "fav_color": {
          "type": "string",
          "enum": [
            "red",
            "green",
            "blue"
          ]
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "id",
        "name"
      ]
    }
  }
}

func ReflectFromType

func ReflectFromType(t reflect.Type) *Schema

ReflectFromType generates root schema using the default Reflector

func (*Schema) AddMeta added in v0.7.0

func (t *Schema) AddMeta(key string, value interface{})

func (*Schema) GetMeta added in v0.7.0

func (t *Schema) GetMeta(key string) (interface{}, bool)

func (*Schema) IsArray added in v0.3.0

func (t *Schema) IsArray() bool

func (*Schema) IsNormal added in v0.3.0

func (t *Schema) IsNormal() bool

func (*Schema) IsNull added in v0.3.0

func (t *Schema) IsNull() bool

func (*Schema) IsObj added in v0.3.0

func (t *Schema) IsObj() bool

func (*Schema) IsSpread added in v0.3.0

func (t *Schema) IsSpread() bool

func (*Schema) MarshalJSON

func (t *Schema) MarshalJSON() ([]byte, error)

func (*Schema) UnmarshalJSON

func (t *Schema) UnmarshalJSON(data []byte) error

UnmarshalJSON is used to parse a schema object or boolean.

type SchemaHelper added in v0.11.0

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

func NewSchemaHelper added in v0.11.0

func NewSchemaHelper(input any) *SchemaHelper

func (*SchemaHelper) GenAccessKeys added in v0.11.0

func (c *SchemaHelper) GenAccessKeys() []string

GenAccessKeys 根据json schema生成可访问的accessKey列表

func (*SchemaHelper) GetRaw added in v0.11.0

func (c *SchemaHelper) GetRaw() map[string]any

func (*SchemaHelper) GetSchemaMapByPointer added in v0.11.0

func (c *SchemaHelper) GetSchemaMapByPointer(schema map[string]interface{}, pointer string) (map[string]interface{}, error)

func (*SchemaHelper) ResolveRef added in v0.11.0

func (c *SchemaHelper) ResolveRef(ref string) (map[string]interface{}, error)

ResolveRef 解析 JSON schema 中的 $ref 引用,返回引用的 JSON 对象

func (*SchemaHelper) SchemaRefParse added in v0.11.0

func (c *SchemaHelper) SchemaRefParse(schema map[string]interface{}) (map[string]interface{}, error)

func (*SchemaHelper) SetSchema added in v0.11.0

func (c *SchemaHelper) SetSchema(input any) error

func (*SchemaHelper) ToStruct added in v0.11.0

func (c *SchemaHelper) ToStruct(out any) error

type TagMapperFunc added in v0.6.0

type TagMapperFunc func(tagName string, tagValue string, now *Schema, parent *Schema)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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