...

Source file src/github.com/qri-io/jsonschema/keywords_core.go

Documentation: github.com/qri-io/jsonschema

     1  package jsonschema
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/url"
     8  	"strings"
     9  
    10  	jptr "github.com/qri-io/jsonpointer"
    11  )
    12  
    13  // SchemaURI defines the $schema JSON Schema keyword
    14  type SchemaURI string
    15  
    16  // NewSchemaURI allocates a new SchemaURI keyword
    17  func NewSchemaURI() Keyword {
    18  	return new(SchemaURI)
    19  }
    20  
    21  // ValidateKeyword implements the Keyword interface for SchemaURI
    22  func (s *SchemaURI) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
    23  	schemaDebug("[SchemaURI] Validating")
    24  }
    25  
    26  // Register implements the Keyword interface for SchemaURI
    27  func (s *SchemaURI) Register(uri string, registry *SchemaRegistry) {}
    28  
    29  // Resolve implements the Keyword interface for SchemaURI
    30  func (s *SchemaURI) Resolve(pointer jptr.Pointer, uri string) *Schema {
    31  	return nil
    32  }
    33  
    34  // ID defines the $id JSON Schema keyword
    35  type ID string
    36  
    37  // NewID allocates a new Id keyword
    38  func NewID() Keyword {
    39  	return new(ID)
    40  }
    41  
    42  // ValidateKeyword implements the Keyword interface for ID
    43  func (i *ID) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
    44  	schemaDebug("[Id] Validating")
    45  	// TODO(arqu): make sure ID is valid URI for draft2019
    46  }
    47  
    48  // Register implements the Keyword interface for ID
    49  func (i *ID) Register(uri string, registry *SchemaRegistry) {}
    50  
    51  // Resolve implements the Keyword interface for ID
    52  func (i *ID) Resolve(pointer jptr.Pointer, uri string) *Schema {
    53  	return nil
    54  }
    55  
    56  // Description defines the description JSON Schema keyword
    57  type Description string
    58  
    59  // NewDescription allocates a new Description keyword
    60  func NewDescription() Keyword {
    61  	return new(Description)
    62  }
    63  
    64  // ValidateKeyword implements the Keyword interface for Description
    65  func (d *Description) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
    66  	schemaDebug("[Description] Validating")
    67  }
    68  
    69  // Register implements the Keyword interface for Description
    70  func (d *Description) Register(uri string, registry *SchemaRegistry) {}
    71  
    72  // Resolve implements the Keyword interface for Description
    73  func (d *Description) Resolve(pointer jptr.Pointer, uri string) *Schema {
    74  	return nil
    75  }
    76  
    77  // Title defines the title JSON Schema keyword
    78  type Title string
    79  
    80  // NewTitle allocates a new Title keyword
    81  func NewTitle() Keyword {
    82  	return new(Title)
    83  }
    84  
    85  // ValidateKeyword implements the Keyword interface for Title
    86  func (t *Title) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
    87  	schemaDebug("[Title] Validating")
    88  }
    89  
    90  // Register implements the Keyword interface for Title
    91  func (t *Title) Register(uri string, registry *SchemaRegistry) {}
    92  
    93  // Resolve implements the Keyword interface for Title
    94  func (t *Title) Resolve(pointer jptr.Pointer, uri string) *Schema {
    95  	return nil
    96  }
    97  
    98  // Comment defines the comment JSON Schema keyword
    99  type Comment string
   100  
   101  // NewComment allocates a new Comment keyword
   102  func NewComment() Keyword {
   103  	return new(Comment)
   104  }
   105  
   106  // ValidateKeyword implements the Keyword interface for Comment
   107  func (c *Comment) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   108  	schemaDebug("[Comment] Validating")
   109  }
   110  
   111  // Register implements the Keyword interface for Comment
   112  func (c *Comment) Register(uri string, registry *SchemaRegistry) {}
   113  
   114  // Resolve implements the Keyword interface for Comment
   115  func (c *Comment) Resolve(pointer jptr.Pointer, uri string) *Schema {
   116  	return nil
   117  }
   118  
   119  // Default defines the default JSON Schema keyword
   120  type Default struct {
   121  	data interface{}
   122  }
   123  
   124  // NewDefault allocates a new Default keyword
   125  func NewDefault() Keyword {
   126  	return &Default{}
   127  }
   128  
   129  // ValidateKeyword implements the Keyword interface for Default
   130  func (d *Default) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   131  	schemaDebug("[Default] Validating")
   132  }
   133  
   134  // Register implements the Keyword interface for Default
   135  func (d *Default) Register(uri string, registry *SchemaRegistry) {}
   136  
   137  // Resolve implements the Keyword interface for Default
   138  func (d *Default) Resolve(pointer jptr.Pointer, uri string) *Schema {
   139  	return nil
   140  }
   141  
   142  // UnmarshalJSON implements the json.Unmarshaler interface for Default
   143  func (d *Default) UnmarshalJSON(data []byte) error {
   144  	var defaultData interface{}
   145  	if err := json.Unmarshal(data, &defaultData); err != nil {
   146  		return err
   147  	}
   148  	*d = Default{
   149  		data: defaultData,
   150  	}
   151  	return nil
   152  }
   153  
   154  // Examples defines the examples JSON Schema keyword
   155  type Examples []interface{}
   156  
   157  // NewExamples allocates a new Examples keyword
   158  func NewExamples() Keyword {
   159  	return new(Examples)
   160  }
   161  
   162  // ValidateKeyword implements the Keyword interface for Examples
   163  func (e *Examples) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   164  	schemaDebug("[Examples] Validating")
   165  }
   166  
   167  // Register implements the Keyword interface for Examples
   168  func (e *Examples) Register(uri string, registry *SchemaRegistry) {}
   169  
   170  // Resolve implements the Keyword interface for Examples
   171  func (e *Examples) Resolve(pointer jptr.Pointer, uri string) *Schema {
   172  	return nil
   173  }
   174  
   175  // ReadOnly defines the readOnly JSON Schema keyword
   176  type ReadOnly bool
   177  
   178  // NewReadOnly allocates a new ReadOnly keyword
   179  func NewReadOnly() Keyword {
   180  	return new(ReadOnly)
   181  }
   182  
   183  // ValidateKeyword implements the Keyword interface for ReadOnly
   184  func (r *ReadOnly) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   185  	schemaDebug("[ReadOnly] Validating")
   186  }
   187  
   188  // Register implements the Keyword interface for ReadOnly
   189  func (r *ReadOnly) Register(uri string, registry *SchemaRegistry) {}
   190  
   191  // Resolve implements the Keyword interface for ReadOnly
   192  func (r *ReadOnly) Resolve(pointer jptr.Pointer, uri string) *Schema {
   193  	return nil
   194  }
   195  
   196  // WriteOnly defines the writeOnly JSON Schema keyword
   197  type WriteOnly bool
   198  
   199  // NewWriteOnly allocates a new WriteOnly keyword
   200  func NewWriteOnly() Keyword {
   201  	return new(WriteOnly)
   202  }
   203  
   204  // ValidateKeyword implements the Keyword interface for WriteOnly
   205  func (w *WriteOnly) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   206  	schemaDebug("[WriteOnly] Validating")
   207  }
   208  
   209  // Register implements the Keyword interface for WriteOnly
   210  func (w *WriteOnly) Register(uri string, registry *SchemaRegistry) {}
   211  
   212  // Resolve implements the Keyword interface for WriteOnly
   213  func (w *WriteOnly) Resolve(pointer jptr.Pointer, uri string) *Schema {
   214  	return nil
   215  }
   216  
   217  // Ref defines the $ref JSON Schema keyword
   218  type Ref struct {
   219  	reference         string
   220  	resolved          *Schema
   221  	resolvedRoot      *Schema
   222  	resolvedFragment  *jptr.Pointer
   223  	fragmentLocalized bool
   224  }
   225  
   226  // NewRef allocates a new Ref keyword
   227  func NewRef() Keyword {
   228  	return new(Ref)
   229  }
   230  
   231  // ValidateKeyword implements the Keyword interface for Ref
   232  func (r *Ref) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   233  	schemaDebug("[Ref] Validating")
   234  	if r.resolved == nil {
   235  		r._resolveRef(ctx, currentState)
   236  		if r.resolved == nil {
   237  			currentState.AddError(data, fmt.Sprintf("failed to resolve schema for ref %s", r.reference))
   238  		}
   239  	}
   240  
   241  	subState := currentState.NewSubState()
   242  	subState.ClearState()
   243  	if r.resolvedRoot != nil {
   244  		subState.BaseURI = r.resolvedRoot.docPath
   245  		subState.Root = r.resolvedRoot
   246  	}
   247  	if r.resolvedFragment != nil && !r.resolvedFragment.IsEmpty() {
   248  		subState.BaseRelativeLocation = r.resolvedFragment
   249  	}
   250  	subState.DescendRelative("$ref")
   251  
   252  	r.resolved.ValidateKeyword(ctx, subState, data)
   253  
   254  	currentState.UpdateEvaluatedPropsAndItems(subState)
   255  }
   256  
   257  // _resolveRef attempts to resolve the reference from the top-level context
   258  func (r *Ref) _resolveRef(ctx context.Context, currentState *ValidationState) {
   259  	if IsLocalSchemaID(r.reference) {
   260  		r.resolved = currentState.LocalRegistry.GetLocal(r.reference)
   261  		if r.resolved != nil {
   262  			return
   263  		}
   264  	}
   265  
   266  	docPath := currentState.BaseURI
   267  	refParts := strings.Split(r.reference, "#")
   268  	address := ""
   269  	if refParts != nil && len(strings.TrimSpace(refParts[0])) > 0 {
   270  		address = refParts[0]
   271  	} else if docPath != "" {
   272  		docPathParts := strings.Split(docPath, "#")
   273  		address = docPathParts[0]
   274  	}
   275  	if len(refParts) > 1 {
   276  		frag := refParts[1]
   277  		if len(frag) > 0 && frag[0] != '/' {
   278  			frag = "/" + frag
   279  			r.fragmentLocalized = true
   280  		}
   281  		fragPointer, err := jptr.Parse(frag)
   282  		if err != nil {
   283  			r.resolvedFragment = &jptr.Pointer{}
   284  		} else {
   285  			r.resolvedFragment = &fragPointer
   286  		}
   287  	} else {
   288  		r.resolvedFragment = &jptr.Pointer{}
   289  	}
   290  
   291  	if address != "" {
   292  		if u, err := url.Parse(address); err == nil {
   293  			if !u.IsAbs() {
   294  				address = currentState.Local.id + address
   295  				if docPath != "" {
   296  					uriFolder := ""
   297  					if docPath[len(docPath)-1] == '/' {
   298  						uriFolder = docPath
   299  					} else {
   300  						corePath := strings.Split(docPath, "#")[0]
   301  						pathComponents := strings.Split(corePath, "/")
   302  						pathComponents = pathComponents[:len(pathComponents)-1]
   303  						uriFolder = strings.Join(pathComponents, "/") + "/"
   304  					}
   305  					address, _ = SafeResolveURL(uriFolder, address)
   306  				}
   307  			}
   308  		}
   309  		r.resolvedRoot = GetSchemaRegistry().Get(ctx, address)
   310  	} else {
   311  		r.resolvedRoot = currentState.Root
   312  	}
   313  
   314  	if r.resolvedRoot == nil {
   315  		return
   316  	}
   317  
   318  	knownSchema := GetSchemaRegistry().GetKnown(r.reference)
   319  	if knownSchema != nil {
   320  		r.resolved = knownSchema
   321  		return
   322  	}
   323  
   324  	localURI := currentState.BaseURI
   325  	if r.resolvedRoot != nil && r.resolvedRoot.docPath != "" {
   326  		localURI = r.resolvedRoot.docPath
   327  		if r.fragmentLocalized && !r.resolvedFragment.IsEmpty() {
   328  			current := r.resolvedFragment.Head()
   329  			sch := currentState.LocalRegistry.GetLocal("#" + *current)
   330  			if sch != nil {
   331  				r.resolved = sch
   332  				return
   333  			}
   334  		}
   335  	}
   336  	r._resolveLocalRef(localURI)
   337  }
   338  
   339  // _resolveLocalRef attempts to resolve the reference from a local context
   340  func (r *Ref) _resolveLocalRef(uri string) {
   341  	if r.resolvedFragment.IsEmpty() {
   342  		r.resolved = r.resolvedRoot
   343  		return
   344  	}
   345  
   346  	if r.resolvedRoot != nil {
   347  		r.resolved = r.resolvedRoot.Resolve(*r.resolvedFragment, uri)
   348  	}
   349  }
   350  
   351  // Register implements the Keyword interface for Ref
   352  func (r *Ref) Register(uri string, registry *SchemaRegistry) {}
   353  
   354  // Resolve implements the Keyword interface for Ref
   355  func (r *Ref) Resolve(pointer jptr.Pointer, uri string) *Schema {
   356  	return nil
   357  }
   358  
   359  // UnmarshalJSON implements the json.Unmarshaler interface for Ref
   360  func (r *Ref) UnmarshalJSON(data []byte) error {
   361  	var ref string
   362  	if err := json.Unmarshal(data, &ref); err != nil {
   363  		return err
   364  	}
   365  	normalizedRef, _ := url.QueryUnescape(ref)
   366  	*r = Ref{
   367  		reference: normalizedRef,
   368  	}
   369  	return nil
   370  }
   371  
   372  // MarshalJSON implements the json.Marshaler interface for Ref
   373  func (r Ref) MarshalJSON() ([]byte, error) {
   374  	return json.Marshal(r.reference)
   375  }
   376  
   377  // RecursiveRef defines the $recursiveRef JSON Schema keyword
   378  type RecursiveRef struct {
   379  	reference        string
   380  	resolved         *Schema
   381  	resolvedRoot     *Schema
   382  	resolvedFragment *jptr.Pointer
   383  
   384  	validatingLocations map[string]bool
   385  }
   386  
   387  // NewRecursiveRef allocates a new RecursiveRef keyword
   388  func NewRecursiveRef() Keyword {
   389  	return new(RecursiveRef)
   390  }
   391  
   392  // ValidateKeyword implements the Keyword interface for RecursiveRef
   393  func (r *RecursiveRef) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   394  	schemaDebug("[RecursiveRef] Validating")
   395  	if r.isLocationVisited(currentState.InstanceLocation.String()) {
   396  		// recursion detected aborting further descent
   397  		return
   398  	}
   399  
   400  	if r.resolved == nil {
   401  		r._resolveRef(ctx, currentState)
   402  		if r.resolved == nil {
   403  			currentState.AddError(data, fmt.Sprintf("failed to resolve schema for ref %s", r.reference))
   404  		}
   405  	}
   406  
   407  	subState := currentState.NewSubState()
   408  	subState.ClearState()
   409  	if r.resolvedRoot != nil {
   410  		subState.BaseURI = r.resolvedRoot.docPath
   411  		subState.Root = r.resolvedRoot
   412  	}
   413  	if r.resolvedFragment != nil && !r.resolvedFragment.IsEmpty() {
   414  		subState.BaseRelativeLocation = r.resolvedFragment
   415  	}
   416  	subState.DescendRelative("$recursiveRef")
   417  
   418  	if r.validatingLocations == nil {
   419  		r.validatingLocations = map[string]bool{}
   420  	}
   421  
   422  	r.validatingLocations[currentState.InstanceLocation.String()] = true
   423  	r.resolved.ValidateKeyword(ctx, subState, data)
   424  	r.validatingLocations[currentState.InstanceLocation.String()] = false
   425  
   426  	currentState.UpdateEvaluatedPropsAndItems(subState)
   427  }
   428  
   429  func (r *RecursiveRef) isLocationVisited(location string) bool {
   430  	if r.validatingLocations == nil {
   431  		return false
   432  	}
   433  	v, ok := r.validatingLocations[location]
   434  	if !ok {
   435  		return false
   436  	}
   437  	return v
   438  }
   439  
   440  // _resolveRef attempts to resolve the reference from the top-level context
   441  func (r *RecursiveRef) _resolveRef(ctx context.Context, currentState *ValidationState) {
   442  	if currentState.RecursiveAnchor != nil {
   443  		if currentState.BaseURI == "" {
   444  			currentState.AddError(nil, fmt.Sprintf("base uri not set"))
   445  			return
   446  		}
   447  		baseSchema := GetSchemaRegistry().Get(ctx, currentState.BaseURI)
   448  		if baseSchema != nil && baseSchema.HasKeyword("$recursiveAnchor") {
   449  			r.resolvedRoot = currentState.RecursiveAnchor
   450  		}
   451  	}
   452  
   453  	if IsLocalSchemaID(r.reference) {
   454  		r.resolved = currentState.LocalRegistry.GetLocal(r.reference)
   455  		if r.resolved != nil {
   456  			return
   457  		}
   458  	}
   459  
   460  	docPath := currentState.BaseURI
   461  	if r.resolvedRoot != nil && r.resolvedRoot.docPath != "" {
   462  		docPath = r.resolvedRoot.docPath
   463  	}
   464  
   465  	refParts := strings.Split(r.reference, "#")
   466  	address := ""
   467  	if refParts != nil && len(strings.TrimSpace(refParts[0])) > 0 {
   468  		address = refParts[0]
   469  	} else {
   470  		address = docPath
   471  	}
   472  
   473  	if len(refParts) > 1 {
   474  
   475  		fragPointer, err := jptr.Parse(refParts[1])
   476  		if err != nil {
   477  			r.resolvedFragment = &jptr.Pointer{}
   478  		} else {
   479  			r.resolvedFragment = &fragPointer
   480  		}
   481  	} else {
   482  		r.resolvedFragment = &jptr.Pointer{}
   483  	}
   484  
   485  	if r.resolvedRoot == nil {
   486  		if address != "" {
   487  			if u, err := url.Parse(address); err == nil {
   488  				if !u.IsAbs() {
   489  					address = currentState.Local.id + address
   490  					if docPath != "" {
   491  						uriFolder := ""
   492  						if docPath[len(docPath)-1] == '/' {
   493  							uriFolder = docPath
   494  						} else {
   495  							corePath := strings.Split(docPath, "#")[0]
   496  							pathComponents := strings.Split(corePath, "/")
   497  							pathComponents = pathComponents[:len(pathComponents)-1]
   498  							uriFolder = strings.Join(pathComponents, "/")
   499  						}
   500  						address, _ = SafeResolveURL(uriFolder, address)
   501  					}
   502  				}
   503  			}
   504  			r.resolvedRoot = GetSchemaRegistry().Get(ctx, address)
   505  		} else {
   506  			r.resolvedRoot = currentState.Root
   507  		}
   508  	}
   509  
   510  	if r.resolvedRoot == nil {
   511  		return
   512  	}
   513  
   514  	knownSchema := GetSchemaRegistry().GetKnown(r.reference)
   515  	if knownSchema != nil {
   516  		r.resolved = knownSchema
   517  		return
   518  	}
   519  
   520  	localURI := currentState.BaseURI
   521  	if r.resolvedRoot != nil && r.resolvedRoot.docPath != "" {
   522  		localURI = r.resolvedRoot.docPath
   523  	}
   524  	r._resolveLocalRef(localURI)
   525  }
   526  
   527  // _resolveLocalRef attempts to resolve the reference from a local context
   528  func (r *RecursiveRef) _resolveLocalRef(uri string) {
   529  	if r.resolvedFragment.IsEmpty() {
   530  		r.resolved = r.resolvedRoot
   531  		return
   532  	}
   533  
   534  	if r.resolvedRoot != nil {
   535  		r.resolved = r.resolvedRoot.Resolve(*r.resolvedFragment, uri)
   536  	}
   537  }
   538  
   539  // Register implements the Keyword interface for RecursiveRef
   540  func (r *RecursiveRef) Register(uri string, registry *SchemaRegistry) {}
   541  
   542  // Resolve implements the Keyword interface for RecursiveRef
   543  func (r *RecursiveRef) Resolve(pointer jptr.Pointer, uri string) *Schema {
   544  	return nil
   545  }
   546  
   547  // UnmarshalJSON implements the json.Unmarshaler interface for RecursiveRef
   548  func (r *RecursiveRef) UnmarshalJSON(data []byte) error {
   549  	var ref string
   550  	if err := json.Unmarshal(data, &ref); err != nil {
   551  		return err
   552  	}
   553  	*r = RecursiveRef{
   554  		reference: ref,
   555  	}
   556  	return nil
   557  }
   558  
   559  // MarshalJSON implements the json.Marshaler interface for RecursiveRef
   560  func (r RecursiveRef) MarshalJSON() ([]byte, error) {
   561  	return json.Marshal(r.reference)
   562  }
   563  
   564  // Anchor defines the $anchor JSON Schema keyword
   565  type Anchor string
   566  
   567  // NewAnchor allocates a new Anchor keyword
   568  func NewAnchor() Keyword {
   569  	return new(Anchor)
   570  }
   571  
   572  // ValidateKeyword implements the Keyword interface for Anchor
   573  func (a *Anchor) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   574  	schemaDebug("[Anchor] Validating")
   575  }
   576  
   577  // Register implements the Keyword interface for Anchor
   578  func (a *Anchor) Register(uri string, registry *SchemaRegistry) {}
   579  
   580  // Resolve implements the Keyword interface for Anchor
   581  func (a *Anchor) Resolve(pointer jptr.Pointer, uri string) *Schema {
   582  	return nil
   583  }
   584  
   585  // RecursiveAnchor defines the $recursiveAnchor JSON Schema keyword
   586  type RecursiveAnchor Schema
   587  
   588  // NewRecursiveAnchor allocates a new RecursiveAnchor keyword
   589  func NewRecursiveAnchor() Keyword {
   590  	return &RecursiveAnchor{}
   591  }
   592  
   593  // Register implements the Keyword interface for RecursiveAnchor
   594  func (r *RecursiveAnchor) Register(uri string, registry *SchemaRegistry) {
   595  	(*Schema)(r).Register(uri, registry)
   596  }
   597  
   598  // Resolve implements the Keyword interface for RecursiveAnchor
   599  func (r *RecursiveAnchor) Resolve(pointer jptr.Pointer, uri string) *Schema {
   600  	return (*Schema)(r).Resolve(pointer, uri)
   601  }
   602  
   603  // ValidateKeyword implements the Keyword interface for RecursiveAnchor
   604  func (r *RecursiveAnchor) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   605  	schemaDebug("[RecursiveAnchor] Validating")
   606  	if currentState.RecursiveAnchor == nil {
   607  		currentState.RecursiveAnchor = currentState.Local
   608  	}
   609  }
   610  
   611  // UnmarshalJSON implements the json.Unmarshaler interface for RecursiveAnchor
   612  func (r *RecursiveAnchor) UnmarshalJSON(data []byte) error {
   613  	sch := &Schema{}
   614  	if err := json.Unmarshal(data, sch); err != nil {
   615  		return err
   616  	}
   617  	*r = (RecursiveAnchor)(*sch)
   618  	return nil
   619  }
   620  
   621  // Defs defines the $defs JSON Schema keyword
   622  type Defs map[string]*Schema
   623  
   624  // NewDefs allocates a new Defs keyword
   625  func NewDefs() Keyword {
   626  	return &Defs{}
   627  }
   628  
   629  // Register implements the Keyword interface for Defs
   630  func (d *Defs) Register(uri string, registry *SchemaRegistry) {
   631  	for _, v := range *d {
   632  		v.Register(uri, registry)
   633  	}
   634  }
   635  
   636  // Resolve implements the Keyword interface for Defs
   637  func (d *Defs) Resolve(pointer jptr.Pointer, uri string) *Schema {
   638  	if pointer == nil {
   639  		return nil
   640  	}
   641  	current := pointer.Head()
   642  	if current == nil {
   643  		return nil
   644  	}
   645  
   646  	if schema, ok := (*d)[*current]; ok {
   647  		return schema.Resolve(pointer.Tail(), uri)
   648  	}
   649  
   650  	return nil
   651  }
   652  
   653  // ValidateKeyword implements the Keyword interface for Defs
   654  func (d Defs) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   655  	schemaDebug("[Defs] Validating")
   656  }
   657  
   658  // JSONProp implements the JSONPather for Defs
   659  func (d Defs) JSONProp(name string) interface{} {
   660  	return d[name]
   661  }
   662  
   663  // JSONChildren implements the JSONContainer interface for Defs
   664  func (d Defs) JSONChildren() (res map[string]JSONPather) {
   665  	res = map[string]JSONPather{}
   666  	for key, sch := range d {
   667  		res[key] = sch
   668  	}
   669  	return
   670  }
   671  
   672  // Void is a placeholder definition for a keyword
   673  type Void struct{}
   674  
   675  // NewVoid allocates a new Void keyword
   676  func NewVoid() Keyword {
   677  	return &Void{}
   678  }
   679  
   680  // Register implements the Keyword interface for Void
   681  func (vo *Void) Register(uri string, registry *SchemaRegistry) {}
   682  
   683  // Resolve implements the Keyword interface for Void
   684  func (vo *Void) Resolve(pointer jptr.Pointer, uri string) *Schema {
   685  	return nil
   686  }
   687  
   688  // ValidateKeyword implements the Keyword interface for Void
   689  func (vo *Void) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
   690  	schemaDebug("[Void] Validating")
   691  	schemaDebug("[Void] WARNING this is a placeholder and should not be used")
   692  	schemaDebug("[Void] Void is always true")
   693  }
   694  

View as plain text