@@ -157,7 +157,9 @@ type Schema struct {
157157 DependentRequired map [string ][]string `json:"dependentRequired,omitempty" yaml:"dependentRequired,omitempty"`
158158
159159 // JSON Schema 2020-12 core keywords
160- Comment string `json:"$comment,omitempty" yaml:"$comment,omitempty"`
160+ Defs Schemas `json:"$defs,omitempty" yaml:"$defs,omitempty"`
161+ SchemaDialect string `json:"$schema,omitempty" yaml:"$schema,omitempty"`
162+ Comment string `json:"$comment,omitempty" yaml:"$comment,omitempty"`
161163
162164 // JSON Schema 2020-12 identity/referencing keywords
163165 SchemaID string `json:"$id,omitempty" yaml:"$id,omitempty"`
@@ -663,6 +665,12 @@ func (schema Schema) MarshalYAML() (any, error) {
663665 if x := schema .DependentRequired ; len (x ) != 0 {
664666 m ["dependentRequired" ] = x
665667 }
668+ if x := schema .Defs ; len (x ) != 0 {
669+ m ["$defs" ] = x
670+ }
671+ if x := schema .SchemaDialect ; x != "" {
672+ m ["$schema" ] = x
673+ }
666674 if x := schema .Comment ; x != "" {
667675 m ["$comment" ] = x
668676 }
@@ -766,6 +774,8 @@ func (schema *Schema) UnmarshalJSON(data []byte) error {
766774 delete (x .Extensions , "then" )
767775 delete (x .Extensions , "else" )
768776 delete (x .Extensions , "dependentRequired" )
777+ delete (x .Extensions , "$defs" )
778+ delete (x .Extensions , "$schema" )
769779 delete (x .Extensions , "$comment" )
770780 delete (x .Extensions , "$id" )
771781 delete (x .Extensions , "$anchor" )
@@ -950,6 +960,10 @@ func (schema Schema) JSONLookup(token string) (any, error) {
950960 }
951961 case "dependentRequired" :
952962 return schema .DependentRequired , nil
963+ case "$defs" :
964+ return schema .Defs , nil
965+ case "$schema" :
966+ return schema .SchemaDialect , nil
953967 case "$comment" :
954968 return schema .Comment , nil
955969 case "$id" :
@@ -1363,7 +1377,10 @@ func (schema *Schema) IsEmpty() bool {
13631377 if len (schema .DependentRequired ) != 0 {
13641378 return false
13651379 }
1366- if schema .Comment != "" {
1380+ if len (schema .Defs ) != 0 {
1381+ return false
1382+ }
1383+ if schema .SchemaDialect != "" || schema .Comment != "" {
13671384 return false
13681385 }
13691386 if schema .SchemaID != "" || schema .Anchor != "" || schema .DynamicRef != "" || schema .DynamicAnchor != "" {
@@ -1637,6 +1654,18 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) ([]*Schema,
16371654 return stack , err
16381655 }
16391656 }
1657+ for _ , name := range componentNames (schema .Defs ) {
1658+ ref := schema .Defs [name ]
1659+ v := ref .Value
1660+ if v == nil {
1661+ return stack , foundUnresolvedRef (ref .Ref )
1662+ }
1663+
1664+ var err error
1665+ if stack , err = v .validate (ctx , stack ); err != nil {
1666+ return stack , err
1667+ }
1668+ }
16401669 if ref := schema .PropertyNames ; ref != nil {
16411670 v := ref .Value
16421671 if v == nil {
@@ -1944,41 +1973,54 @@ func (schema *Schema) visitNotOperation(settings *schemaValidationSettings, valu
19441973
19451974// If the XOF operations pass successfully, abort further run of validation, as they will already be satisfied (unless the schema
19461975// itself is badly specified
1976+ // resolveDiscriminatorRef resolves the discriminator reference for oneOf/anyOf validation.
1977+ // Returns the discriminator ref string and any error encountered during resolution.
1978+ func (schema * Schema ) resolveDiscriminatorRef (value any ) (string , error ) {
1979+ if schema .Discriminator == nil {
1980+ return "" , nil
1981+ }
1982+ pn := schema .Discriminator .PropertyName
1983+ valuemap , okcheck := value .(map [string ]any )
1984+ if ! okcheck {
1985+ return "" , nil
1986+ }
1987+ discriminatorVal , okcheck := valuemap [pn ]
1988+ if ! okcheck {
1989+ return "" , & SchemaError {
1990+ Schema : schema ,
1991+ SchemaField : "discriminator" ,
1992+ Reason : fmt .Sprintf ("input does not contain the discriminator property %q" , pn ),
1993+ }
1994+ }
1995+
1996+ discriminatorValString , okcheck := discriminatorVal .(string )
1997+ if ! okcheck {
1998+ return "" , & SchemaError {
1999+ Value : discriminatorVal ,
2000+ Schema : schema ,
2001+ SchemaField : "discriminator" ,
2002+ Reason : fmt .Sprintf ("value of discriminator property %q is not a string" , pn ),
2003+ }
2004+ }
2005+
2006+ if discriminatorRef , okcheck := schema .Discriminator .Mapping [discriminatorValString ]; len (schema .Discriminator .Mapping ) > 0 && ! okcheck {
2007+ return "" , & SchemaError {
2008+ Value : discriminatorVal ,
2009+ Schema : schema ,
2010+ SchemaField : "discriminator" ,
2011+ Reason : fmt .Sprintf ("discriminator property %q has invalid value" , pn ),
2012+ }
2013+ } else {
2014+ return discriminatorRef , nil
2015+ }
2016+ }
2017+
19472018func (schema * Schema ) visitXOFOperations (settings * schemaValidationSettings , value any ) (err error , run bool ) {
19482019 var visitedOneOf , visitedAnyOf , visitedAllOf bool
19492020 if v := schema .OneOf ; len (v ) > 0 {
1950- var discriminatorRef string
1951- if schema .Discriminator != nil {
1952- pn := schema .Discriminator .PropertyName
1953- if valuemap , okcheck := value .(map [string ]any ); okcheck {
1954- discriminatorVal , okcheck := valuemap [pn ]
1955- if ! okcheck {
1956- return & SchemaError {
1957- Schema : schema ,
1958- SchemaField : "discriminator" ,
1959- Reason : fmt .Sprintf ("input does not contain the discriminator property %q" , pn ),
1960- }, false
1961- }
1962-
1963- discriminatorValString , okcheck := discriminatorVal .(string )
1964- if ! okcheck {
1965- return & SchemaError {
1966- Value : discriminatorVal ,
1967- Schema : schema ,
1968- SchemaField : "discriminator" ,
1969- Reason : fmt .Sprintf ("value of discriminator property %q is not a string" , pn ),
1970- }, false
1971- }
1972-
1973- if discriminatorRef , okcheck = schema .Discriminator .Mapping [discriminatorValString ]; len (schema .Discriminator .Mapping ) > 0 && ! okcheck {
1974- return & SchemaError {
1975- Value : discriminatorVal ,
1976- Schema : schema ,
1977- SchemaField : "discriminator" ,
1978- Reason : fmt .Sprintf ("discriminator property %q has invalid value" , pn ),
1979- }, false
1980- }
1981- }
2021+ discriminatorRef , err := schema .resolveDiscriminatorRef (value )
2022+ if err != nil {
2023+ return err , false
19822024 }
19832025
19842026 var (
@@ -2040,38 +2082,9 @@ func (schema *Schema) visitXOFOperations(settings *schemaValidationSettings, val
20402082 }
20412083
20422084 if v := schema .AnyOf ; len (v ) > 0 {
2043- var discriminatorRef string
2044- if schema .Discriminator != nil {
2045- pn := schema .Discriminator .PropertyName
2046- if valuemap , okcheck := value .(map [string ]any ); okcheck {
2047- discriminatorVal , okcheck := valuemap [pn ]
2048- if ! okcheck {
2049- return & SchemaError {
2050- Schema : schema ,
2051- SchemaField : "discriminator" ,
2052- Reason : fmt .Sprintf ("input does not contain the discriminator property %q" , pn ),
2053- }, false
2054- }
2055-
2056- discriminatorValString , okcheck := discriminatorVal .(string )
2057- if ! okcheck {
2058- return & SchemaError {
2059- Value : discriminatorVal ,
2060- Schema : schema ,
2061- SchemaField : "discriminator" ,
2062- Reason : fmt .Sprintf ("value of discriminator property %q is not a string" , pn ),
2063- }, false
2064- }
2065-
2066- if discriminatorRef , okcheck = schema .Discriminator .Mapping [discriminatorValString ]; len (schema .Discriminator .Mapping ) > 0 && ! okcheck {
2067- return & SchemaError {
2068- Value : discriminatorVal ,
2069- Schema : schema ,
2070- SchemaField : "discriminator" ,
2071- Reason : fmt .Sprintf ("discriminator property %q has invalid value" , pn ),
2072- }, false
2073- }
2074- }
2085+ discriminatorRef , err := schema .resolveDiscriminatorRef (value )
2086+ if err != nil {
2087+ return err , false
20752088 }
20762089
20772090 var (
0 commit comments