Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_Store
coverage.txt
.vscode
.vscode
.idea
7 changes: 7 additions & 0 deletions keyword.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ type Keyword interface {
Resolve(pointer jptr.Pointer, uri string) *Schema
}

// SchemaKeyword is a kind of Keyword which exposes a GetSchema method for returning the underlying Schema. This should
// be implemented by other keywords whose value is a Schema (i.e. via a type definition like `type Not Schema`).
type SchemaKeyword interface {
Keyword
GetSchema() *Schema
}

// KeyMaker is a function that generates instances of a Keyword.
// Calls to KeyMaker will be passed directly to json.Marshal,
// so the returned value should be a pointer
Expand Down
28 changes: 25 additions & 3 deletions keywords_array.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,18 @@ func (it Items) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for Items
func (it Items) JSONChildren() (res map[string]JSONPather) {
res = map[string]JSONPather{}
func (it Items) JSONChildren() (res map[string]interface{}) {
res = map[string]interface{}{}

if it.single {
res["."] = it.Schemas[0]
return
}

for i, sch := range it.Schemas {
res[strconv.Itoa(i)] = sch
}

return
}

Expand Down Expand Up @@ -265,13 +272,18 @@ func (c *Contains) ValidateKeyword(ctx context.Context, currentState *Validation
}
}

// GetSchema implements the SchemaKeyword for Contains
func (c *Contains) GetSchema() *Schema {
return (*Schema)(c)
}

// JSONProp implements the JSONPather for Contains
func (c Contains) JSONProp(name string) interface{} {
return Schema(c).JSONProp(name)
}

// JSONChildren implements the JSONContainer interface for Contains
func (c Contains) JSONChildren() (res map[string]JSONPather) {
func (c Contains) JSONChildren() (res map[string]interface{}) {
return Schema(c).JSONChildren()
}

Expand Down Expand Up @@ -383,6 +395,11 @@ func (ai *AdditionalItems) ValidateKeyword(ctx context.Context, currentState *Va
}
}

// GetSchema implements the SchemaKeyword for AdditionalItems
func (ai *AdditionalItems) GetSchema() *Schema {
return (*Schema)(ai)
}

// UnmarshalJSON implements the json.Unmarshaler interface for AdditionalItems
func (ai *AdditionalItems) UnmarshalJSON(data []byte) error {
sch := &Schema{}
Expand Down Expand Up @@ -433,6 +450,11 @@ func (ui *UnevaluatedItems) ValidateKeyword(ctx context.Context, currentState *V
}
}

// GetSchema implements the SchemaKeyword for UnevaluatedItems
func (ui *UnevaluatedItems) GetSchema() *Schema {
return (*Schema)(ui)
}

// UnmarshalJSON implements the json.Unmarshaler interface for UnevaluatedItems
func (ui *UnevaluatedItems) UnmarshalJSON(data []byte) error {
sch := &Schema{}
Expand Down
19 changes: 12 additions & 7 deletions keywords_boolean.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ func (a AllOf) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for AllOf
func (a AllOf) JSONChildren() (res map[string]JSONPather) {
res = map[string]JSONPather{}
func (a AllOf) JSONChildren() (res map[string]interface{}) {
res = map[string]interface{}{}
for i, sch := range a {
res[strconv.Itoa(i)] = sch
}
Expand Down Expand Up @@ -163,8 +163,8 @@ func (a AnyOf) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for AnyOf
func (a AnyOf) JSONChildren() (res map[string]JSONPather) {
res = map[string]JSONPather{}
func (a AnyOf) JSONChildren() (res map[string]interface{}) {
res = map[string]interface{}{}
for i, sch := range a {
res[strconv.Itoa(i)] = sch
}
Expand Down Expand Up @@ -252,8 +252,8 @@ func (o OneOf) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for OneOf
func (o OneOf) JSONChildren() (res map[string]JSONPather) {
res = map[string]JSONPather{}
func (o OneOf) JSONChildren() (res map[string]interface{}) {
res = map[string]interface{}{}
for i, sch := range o {
res[strconv.Itoa(i)] = sch
}
Expand Down Expand Up @@ -293,13 +293,18 @@ func (n *Not) ValidateKeyword(ctx context.Context, currentState *ValidationState
}
}

// GetSchema implements the SchemaKeyword for Not
func (n *Not) GetSchema() *Schema {
return (*Schema)(n)
}

// JSONProp implements the JSONPather for Not
func (n Not) JSONProp(name string) interface{} {
return Schema(n).JSONProp(name)
}

// JSONChildren implements the JSONContainer interface for Not
func (n Not) JSONChildren() (res map[string]JSONPather) {
func (n Not) JSONChildren() (res map[string]interface{}) {
return Schema(n).JSONChildren()
}

Expand Down
21 changes: 18 additions & 3 deletions keywords_conditional.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,18 @@ func (f *If) ValidateKeyword(ctx context.Context, currentState *ValidationState,
currentState.Misc["ifResult"] = subState.IsValid()
}

// GetSchema implements the SchemaKeyword for If
func (f *If) GetSchema() *Schema {
return (*Schema)(f)
}

// JSONProp implements the JSONPather for If
func (f If) JSONProp(name string) interface{} {
return Schema(f).JSONProp(name)
}

// JSONChildren implements the JSONContainer interface for If
func (f If) JSONChildren() (res map[string]JSONPather) {
func (f If) JSONChildren() (res map[string]interface{}) {
return Schema(f).JSONChildren()
}

Expand Down Expand Up @@ -116,13 +121,18 @@ func (t *Then) ValidateKeyword(ctx context.Context, currentState *ValidationStat
currentState.UpdateEvaluatedPropsAndItems(subState)
}

// GetSchema implements the SchemaKeyword for Then
func (t *Then) GetSchema() *Schema {
return (*Schema)(t)
}

// JSONProp implements the JSONPather for Then
func (t Then) JSONProp(name string) interface{} {
return Schema(t).JSONProp(name)
}

// JSONChildren implements the JSONContainer interface for Then
func (t Then) JSONChildren() (res map[string]JSONPather) {
func (t Then) JSONChildren() (res map[string]interface{}) {
return Schema(t).JSONChildren()
}

Expand Down Expand Up @@ -180,13 +190,18 @@ func (e *Else) ValidateKeyword(ctx context.Context, currentState *ValidationStat
sch.ValidateKeyword(ctx, subState, data)
}

// GetSchema implements the SchemaKeyword for Else
func (e *Else) GetSchema() *Schema {
return (*Schema)(e)
}

// JSONProp implements the JSONPather for Else
func (e Else) JSONProp(name string) interface{} {
return Schema(e).JSONProp(name)
}

// JSONChildren implements the JSONContainer interface for Else
func (e Else) JSONChildren() (res map[string]JSONPather) {
func (e Else) JSONChildren() (res map[string]interface{}) {
return Schema(e).JSONChildren()
}

Expand Down
4 changes: 2 additions & 2 deletions keywords_core.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,8 @@ func (d Defs) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for Defs
func (d Defs) JSONChildren() (res map[string]JSONPather) {
res = map[string]JSONPather{}
func (d Defs) JSONChildren() (res map[string]interface{}) {
res = map[string]interface{}{}
for key, sch := range d {
res[key] = sch
}
Expand Down
48 changes: 39 additions & 9 deletions keywords_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ func (p Properties) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for Properties
func (p Properties) JSONChildren() (res map[string]JSONPather) {
res = map[string]JSONPather{}
func (p Properties) JSONChildren() (res map[string]interface{}) {
res = map[string]interface{}{}
for key, sch := range p {
res[key] = sch
}
Expand Down Expand Up @@ -252,8 +252,8 @@ func (p PatternProperties) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for PatternProperties
func (p PatternProperties) JSONChildren() (res map[string]JSONPather) {
res = map[string]JSONPather{}
func (p PatternProperties) JSONChildren() (res map[string]interface{}) {
res = map[string]interface{}{}
for i, pp := range p {
res[strconv.Itoa(i)] = pp.schema
}
Expand Down Expand Up @@ -341,6 +341,11 @@ func (ap *AdditionalProperties) ValidateKeyword(ctx context.Context, currentStat
}
}

// GetSchema implements the SchemaKeyword for AdditionalProperties
func (ap *AdditionalProperties) GetSchema() *Schema {
return (*Schema)(ap)
}

// UnmarshalJSON implements the json.Unmarshaler interface for AdditionalProperties
func (ap *AdditionalProperties) UnmarshalJSON(data []byte) error {
sch := &Schema{}
Expand All @@ -351,6 +356,16 @@ func (ap *AdditionalProperties) UnmarshalJSON(data []byte) error {
return nil
}

// JSONProp implements the JSONPather for AdditionalProperties
func (ap AdditionalProperties) JSONProp(name string) interface{} {
return Schema(ap).JSONProp(name)
}

// JSONChildren implements the JSONContainer interface for AdditionalProperties
func (ap AdditionalProperties) JSONChildren() (res map[string]interface{}) {
return Schema(ap).JSONChildren()
}

// PropertyNames defines the propertyNames JSON Schema keyword
type PropertyNames Schema

Expand Down Expand Up @@ -383,13 +398,18 @@ func (p *PropertyNames) ValidateKeyword(ctx context.Context, currentState *Valid
}
}

// GetSchema implements the SchemaKeyword for PropertyNames
func (p *PropertyNames) GetSchema() *Schema {
return (*Schema)(p)
}

// JSONProp implements the JSONPather for PropertyNames
func (p PropertyNames) JSONProp(name string) interface{} {
return Schema(p).JSONProp(name)
}

// JSONChildren implements the JSONContainer interface for PropertyNames
func (p PropertyNames) JSONChildren() (res map[string]JSONPather) {
func (p PropertyNames) JSONChildren() (res map[string]interface{}) {
return Schema(p).JSONChildren()
}

Expand Down Expand Up @@ -478,8 +498,8 @@ func (d DependentSchemas) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for DependentSchemas
func (d DependentSchemas) JSONChildren() (r map[string]JSONPather) {
r = map[string]JSONPather{}
func (d DependentSchemas) JSONChildren() (r map[string]interface{}) {
r = map[string]interface{}{}
for key, val := range d {
r[key] = val
}
Expand Down Expand Up @@ -519,6 +539,11 @@ func (d *SchemaDependency) ValidateKeyword(ctx context.Context, currentState *Va
d.schema.ValidateKeyword(ctx, subState, data)
}

// GetSchema implements the SchemaKeyword for SchemaDependency
func (d *SchemaDependency) GetSchema() *Schema {
return d.schema
}

// MarshalJSON implements the json.Marshaler interface for SchemaDependency
func (d SchemaDependency) MarshalJSON() ([]byte, error) {
return json.Marshal(d.schema)
Expand Down Expand Up @@ -591,8 +616,8 @@ func (d DependentRequired) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for DependentRequired
func (d DependentRequired) JSONChildren() (r map[string]JSONPather) {
r = map[string]JSONPather{}
func (d DependentRequired) JSONChildren() (r map[string]interface{}) {
r = map[string]interface{}{}
for key, val := range d {
r[key] = val
}
Expand Down Expand Up @@ -681,6 +706,11 @@ func (up *UnevaluatedProperties) ValidateKeyword(ctx context.Context, currentSta
}
}

// GetSchema implements the SchemaKeyword for UnevaluatedProperties
func (up *UnevaluatedProperties) GetSchema() *Schema {
return (*Schema)(up)
}

// UnmarshalJSON implements the json.Unmarshaler interface for UnevaluatedProperties
func (up *UnevaluatedProperties) UnmarshalJSON(data []byte) error {
sch := &Schema{}
Expand Down
4 changes: 2 additions & 2 deletions keywords_standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ func (e Enum) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for Enum
func (e Enum) JSONChildren() (res map[string]JSONPather) {
res = map[string]JSONPather{}
func (e Enum) JSONChildren() (res map[string]interface{}) {
res = map[string]interface{}{}
for i, bs := range e {
res[strconv.Itoa(i)] = bs
}
Expand Down
14 changes: 8 additions & 6 deletions schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,20 +146,22 @@ func (s Schema) JSONProp(name string) interface{} {
}

// JSONChildren implements the JSONContainer interface for Schema
func (s Schema) JSONChildren() map[string]JSONPather {
ch := map[string]JSONPather{}
func (s Schema) JSONChildren() map[string]interface{} {
ch := map[string]interface{}{}

if s.keywords != nil {
for key, val := range s.keywords {
if jp, ok := val.(JSONPather); ok {
ch[key] = jp
}
for _, key := range s.orderedkeywords {
ch[key] = s.keywords[key]
}
}

return ch
}

func (s *Schema) GetSchema() *Schema {
return s
}

// _schema is an internal struct for encoding & decoding purposes
type _schema struct {
ID string `json:"$id,omitempty"`
Expand Down
6 changes: 3 additions & 3 deletions traversal.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ type JSONPather interface {
// JSONContainer is an interface that enables tree traversal by listing
// the immideate children of an object
type JSONContainer interface {
// JSONChildren should return all immidiate children of this element
JSONChildren() map[string]JSONPather
// JSONChildren should return all immediate children of this element
JSONChildren() map[string]interface{}
}

func walkJSON(elem JSONPather, fn func(elem JSONPather) error) error {
func walkJSON(elem interface{}, fn func(elem interface{}) error) error {
if err := fn(elem); err != nil {
return err
}
Expand Down
Loading