k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/validation/spec/schema.go (about)

     1  // Copyright 2015 go-swagger maintainers
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package spec
    16  
    17  import (
    18  	"encoding/json"
    19  	"fmt"
    20  	"net/url"
    21  	"strings"
    22  
    23  	"github.com/go-openapi/swag"
    24  	"k8s.io/kube-openapi/pkg/internal"
    25  	jsonv2 "k8s.io/kube-openapi/pkg/internal/third_party/go-json-experiment/json"
    26  )
    27  
    28  // BooleanProperty creates a boolean property
    29  func BooleanProperty() *Schema {
    30  	return &Schema{SchemaProps: SchemaProps{Type: []string{"boolean"}}}
    31  }
    32  
    33  // BoolProperty creates a boolean property
    34  func BoolProperty() *Schema { return BooleanProperty() }
    35  
    36  // StringProperty creates a string property
    37  func StringProperty() *Schema {
    38  	return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}}
    39  }
    40  
    41  // CharProperty creates a string property
    42  func CharProperty() *Schema {
    43  	return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}}}
    44  }
    45  
    46  // Float64Property creates a float64/double property
    47  func Float64Property() *Schema {
    48  	return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "double"}}
    49  }
    50  
    51  // Float32Property creates a float32/float property
    52  func Float32Property() *Schema {
    53  	return &Schema{SchemaProps: SchemaProps{Type: []string{"number"}, Format: "float"}}
    54  }
    55  
    56  // Int8Property creates an int8 property
    57  func Int8Property() *Schema {
    58  	return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int8"}}
    59  }
    60  
    61  // Int16Property creates an int16 property
    62  func Int16Property() *Schema {
    63  	return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int16"}}
    64  }
    65  
    66  // Int32Property creates an int32 property
    67  func Int32Property() *Schema {
    68  	return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int32"}}
    69  }
    70  
    71  // Int64Property creates an int64 property
    72  func Int64Property() *Schema {
    73  	return &Schema{SchemaProps: SchemaProps{Type: []string{"integer"}, Format: "int64"}}
    74  }
    75  
    76  // StrFmtProperty creates a property for the named string format
    77  func StrFmtProperty(format string) *Schema {
    78  	return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: format}}
    79  }
    80  
    81  // DateProperty creates a date property
    82  func DateProperty() *Schema {
    83  	return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date"}}
    84  }
    85  
    86  // DateTimeProperty creates a date time property
    87  func DateTimeProperty() *Schema {
    88  	return &Schema{SchemaProps: SchemaProps{Type: []string{"string"}, Format: "date-time"}}
    89  }
    90  
    91  // MapProperty creates a map property
    92  func MapProperty(property *Schema) *Schema {
    93  	return &Schema{SchemaProps: SchemaProps{Type: []string{"object"},
    94  		AdditionalProperties: &SchemaOrBool{Allows: true, Schema: property}}}
    95  }
    96  
    97  // RefProperty creates a ref property
    98  func RefProperty(name string) *Schema {
    99  	return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}}
   100  }
   101  
   102  // RefSchema creates a ref property
   103  func RefSchema(name string) *Schema {
   104  	return &Schema{SchemaProps: SchemaProps{Ref: MustCreateRef(name)}}
   105  }
   106  
   107  // ArrayProperty creates an array property
   108  func ArrayProperty(items *Schema) *Schema {
   109  	if items == nil {
   110  		return &Schema{SchemaProps: SchemaProps{Type: []string{"array"}}}
   111  	}
   112  	return &Schema{SchemaProps: SchemaProps{Items: &SchemaOrArray{Schema: items}, Type: []string{"array"}}}
   113  }
   114  
   115  // ComposedSchema creates a schema with allOf
   116  func ComposedSchema(schemas ...Schema) *Schema {
   117  	s := new(Schema)
   118  	s.AllOf = schemas
   119  	return s
   120  }
   121  
   122  // SchemaURL represents a schema url
   123  type SchemaURL string
   124  
   125  // MarshalJSON marshal this to JSON
   126  func (r SchemaURL) MarshalJSON() ([]byte, error) {
   127  	if r == "" {
   128  		return []byte("{}"), nil
   129  	}
   130  	v := map[string]interface{}{"$schema": string(r)}
   131  	return json.Marshal(v)
   132  }
   133  
   134  // UnmarshalJSON unmarshal this from JSON
   135  func (r *SchemaURL) UnmarshalJSON(data []byte) error {
   136  	var v map[string]interface{}
   137  	if err := json.Unmarshal(data, &v); err != nil {
   138  		return err
   139  	}
   140  	return r.fromMap(v)
   141  }
   142  
   143  func (r *SchemaURL) fromMap(v map[string]interface{}) error {
   144  	if v == nil {
   145  		return nil
   146  	}
   147  	if vv, ok := v["$schema"]; ok {
   148  		if str, ok := vv.(string); ok {
   149  			u, err := url.Parse(str)
   150  			if err != nil {
   151  				return err
   152  			}
   153  
   154  			*r = SchemaURL(u.String())
   155  		}
   156  	}
   157  	return nil
   158  }
   159  
   160  // SchemaProps describes a JSON schema (draft 4)
   161  type SchemaProps struct {
   162  	ID                   string            `json:"id,omitempty"`
   163  	Ref                  Ref               `json:"-"`
   164  	Schema               SchemaURL         `json:"-"`
   165  	Description          string            `json:"description,omitempty"`
   166  	Type                 StringOrArray     `json:"type,omitempty"`
   167  	Nullable             bool              `json:"nullable,omitempty"`
   168  	Format               string            `json:"format,omitempty"`
   169  	Title                string            `json:"title,omitempty"`
   170  	Default              interface{}       `json:"default,omitempty"`
   171  	Maximum              *float64          `json:"maximum,omitempty"`
   172  	ExclusiveMaximum     bool              `json:"exclusiveMaximum,omitempty"`
   173  	Minimum              *float64          `json:"minimum,omitempty"`
   174  	ExclusiveMinimum     bool              `json:"exclusiveMinimum,omitempty"`
   175  	MaxLength            *int64            `json:"maxLength,omitempty"`
   176  	MinLength            *int64            `json:"minLength,omitempty"`
   177  	Pattern              string            `json:"pattern,omitempty"`
   178  	MaxItems             *int64            `json:"maxItems,omitempty"`
   179  	MinItems             *int64            `json:"minItems,omitempty"`
   180  	UniqueItems          bool              `json:"uniqueItems,omitempty"`
   181  	MultipleOf           *float64          `json:"multipleOf,omitempty"`
   182  	Enum                 []interface{}     `json:"enum,omitempty"`
   183  	MaxProperties        *int64            `json:"maxProperties,omitempty"`
   184  	MinProperties        *int64            `json:"minProperties,omitempty"`
   185  	Required             []string          `json:"required,omitempty"`
   186  	Items                *SchemaOrArray    `json:"items,omitempty"`
   187  	AllOf                []Schema          `json:"allOf,omitempty"`
   188  	OneOf                []Schema          `json:"oneOf,omitempty"`
   189  	AnyOf                []Schema          `json:"anyOf,omitempty"`
   190  	Not                  *Schema           `json:"not,omitempty"`
   191  	Properties           map[string]Schema `json:"properties,omitempty"`
   192  	AdditionalProperties *SchemaOrBool     `json:"additionalProperties,omitempty"`
   193  	PatternProperties    map[string]Schema `json:"patternProperties,omitempty"`
   194  	Dependencies         Dependencies      `json:"dependencies,omitempty"`
   195  	AdditionalItems      *SchemaOrBool     `json:"additionalItems,omitempty"`
   196  	Definitions          Definitions       `json:"definitions,omitempty"`
   197  }
   198  
   199  // Marshaling structure only, always edit along with corresponding
   200  // struct (or compilation will fail).
   201  type schemaPropsOmitZero struct {
   202  	ID                   string            `json:"id,omitempty"`
   203  	Ref                  Ref               `json:"-"`
   204  	Schema               SchemaURL         `json:"-"`
   205  	Description          string            `json:"description,omitempty"`
   206  	Type                 StringOrArray     `json:"type,omitzero"`
   207  	Nullable             bool              `json:"nullable,omitzero"`
   208  	Format               string            `json:"format,omitempty"`
   209  	Title                string            `json:"title,omitempty"`
   210  	Default              interface{}       `json:"default,omitzero"`
   211  	Maximum              *float64          `json:"maximum,omitempty"`
   212  	ExclusiveMaximum     bool              `json:"exclusiveMaximum,omitzero"`
   213  	Minimum              *float64          `json:"minimum,omitempty"`
   214  	ExclusiveMinimum     bool              `json:"exclusiveMinimum,omitzero"`
   215  	MaxLength            *int64            `json:"maxLength,omitempty"`
   216  	MinLength            *int64            `json:"minLength,omitempty"`
   217  	Pattern              string            `json:"pattern,omitempty"`
   218  	MaxItems             *int64            `json:"maxItems,omitempty"`
   219  	MinItems             *int64            `json:"minItems,omitempty"`
   220  	UniqueItems          bool              `json:"uniqueItems,omitzero"`
   221  	MultipleOf           *float64          `json:"multipleOf,omitempty"`
   222  	Enum                 []interface{}     `json:"enum,omitempty"`
   223  	MaxProperties        *int64            `json:"maxProperties,omitempty"`
   224  	MinProperties        *int64            `json:"minProperties,omitempty"`
   225  	Required             []string          `json:"required,omitempty"`
   226  	Items                *SchemaOrArray    `json:"items,omitzero"`
   227  	AllOf                []Schema          `json:"allOf,omitempty"`
   228  	OneOf                []Schema          `json:"oneOf,omitempty"`
   229  	AnyOf                []Schema          `json:"anyOf,omitempty"`
   230  	Not                  *Schema           `json:"not,omitzero"`
   231  	Properties           map[string]Schema `json:"properties,omitempty"`
   232  	AdditionalProperties *SchemaOrBool     `json:"additionalProperties,omitzero"`
   233  	PatternProperties    map[string]Schema `json:"patternProperties,omitempty"`
   234  	Dependencies         Dependencies      `json:"dependencies,omitempty"`
   235  	AdditionalItems      *SchemaOrBool     `json:"additionalItems,omitzero"`
   236  	Definitions          Definitions       `json:"definitions,omitempty"`
   237  }
   238  
   239  // SwaggerSchemaProps are additional properties supported by swagger schemas, but not JSON-schema (draft 4)
   240  type SwaggerSchemaProps struct {
   241  	Discriminator string                 `json:"discriminator,omitempty"`
   242  	ReadOnly      bool                   `json:"readOnly,omitempty"`
   243  	ExternalDocs  *ExternalDocumentation `json:"externalDocs,omitempty"`
   244  	Example       interface{}            `json:"example,omitempty"`
   245  }
   246  
   247  // Marshaling structure only, always edit along with corresponding
   248  // struct (or compilation will fail).
   249  type swaggerSchemaPropsOmitZero struct {
   250  	Discriminator string                 `json:"discriminator,omitempty"`
   251  	ReadOnly      bool                   `json:"readOnly,omitzero"`
   252  	ExternalDocs  *ExternalDocumentation `json:"externalDocs,omitzero"`
   253  	Example       interface{}            `json:"example,omitempty"`
   254  }
   255  
   256  // Schema the schema object allows the definition of input and output data types.
   257  // These types can be objects, but also primitives and arrays.
   258  // This object is based on the [JSON Schema Specification Draft 4](http://json-schema.org/)
   259  // and uses a predefined subset of it.
   260  // On top of this subset, there are extensions provided by this specification to allow for more complete documentation.
   261  //
   262  // For more information: http://goo.gl/8us55a#schemaObject
   263  type Schema struct {
   264  	VendorExtensible
   265  	SchemaProps
   266  	SwaggerSchemaProps
   267  	ExtraProps map[string]interface{} `json:"-"`
   268  }
   269  
   270  // WithID sets the id for this schema, allows for chaining
   271  func (s *Schema) WithID(id string) *Schema {
   272  	s.ID = id
   273  	return s
   274  }
   275  
   276  // WithTitle sets the title for this schema, allows for chaining
   277  func (s *Schema) WithTitle(title string) *Schema {
   278  	s.Title = title
   279  	return s
   280  }
   281  
   282  // WithDescription sets the description for this schema, allows for chaining
   283  func (s *Schema) WithDescription(description string) *Schema {
   284  	s.Description = description
   285  	return s
   286  }
   287  
   288  // WithProperties sets the properties for this schema
   289  func (s *Schema) WithProperties(schemas map[string]Schema) *Schema {
   290  	s.Properties = schemas
   291  	return s
   292  }
   293  
   294  // SetProperty sets a property on this schema
   295  func (s *Schema) SetProperty(name string, schema Schema) *Schema {
   296  	if s.Properties == nil {
   297  		s.Properties = make(map[string]Schema)
   298  	}
   299  	s.Properties[name] = schema
   300  	return s
   301  }
   302  
   303  // WithAllOf sets the all of property
   304  func (s *Schema) WithAllOf(schemas ...Schema) *Schema {
   305  	s.AllOf = schemas
   306  	return s
   307  }
   308  
   309  // WithMaxProperties sets the max number of properties an object can have
   310  func (s *Schema) WithMaxProperties(max int64) *Schema {
   311  	s.MaxProperties = &max
   312  	return s
   313  }
   314  
   315  // WithMinProperties sets the min number of properties an object must have
   316  func (s *Schema) WithMinProperties(min int64) *Schema {
   317  	s.MinProperties = &min
   318  	return s
   319  }
   320  
   321  // Typed sets the type of this schema for a single value item
   322  func (s *Schema) Typed(tpe, format string) *Schema {
   323  	s.Type = []string{tpe}
   324  	s.Format = format
   325  	return s
   326  }
   327  
   328  // AddType adds a type with potential format to the types for this schema
   329  func (s *Schema) AddType(tpe, format string) *Schema {
   330  	s.Type = append(s.Type, tpe)
   331  	if format != "" {
   332  		s.Format = format
   333  	}
   334  	return s
   335  }
   336  
   337  // AsNullable flags this schema as nullable.
   338  func (s *Schema) AsNullable() *Schema {
   339  	s.Nullable = true
   340  	return s
   341  }
   342  
   343  // CollectionOf a fluent builder method for an array parameter
   344  func (s *Schema) CollectionOf(items Schema) *Schema {
   345  	s.Type = []string{jsonArray}
   346  	s.Items = &SchemaOrArray{Schema: &items}
   347  	return s
   348  }
   349  
   350  // WithDefault sets the default value on this parameter
   351  func (s *Schema) WithDefault(defaultValue interface{}) *Schema {
   352  	s.Default = defaultValue
   353  	return s
   354  }
   355  
   356  // WithRequired flags this parameter as required
   357  func (s *Schema) WithRequired(items ...string) *Schema {
   358  	s.Required = items
   359  	return s
   360  }
   361  
   362  // AddRequired  adds field names to the required properties array
   363  func (s *Schema) AddRequired(items ...string) *Schema {
   364  	s.Required = append(s.Required, items...)
   365  	return s
   366  }
   367  
   368  // WithMaxLength sets a max length value
   369  func (s *Schema) WithMaxLength(max int64) *Schema {
   370  	s.MaxLength = &max
   371  	return s
   372  }
   373  
   374  // WithMinLength sets a min length value
   375  func (s *Schema) WithMinLength(min int64) *Schema {
   376  	s.MinLength = &min
   377  	return s
   378  }
   379  
   380  // WithPattern sets a pattern value
   381  func (s *Schema) WithPattern(pattern string) *Schema {
   382  	s.Pattern = pattern
   383  	return s
   384  }
   385  
   386  // WithMultipleOf sets a multiple of value
   387  func (s *Schema) WithMultipleOf(number float64) *Schema {
   388  	s.MultipleOf = &number
   389  	return s
   390  }
   391  
   392  // WithMaximum sets a maximum number value
   393  func (s *Schema) WithMaximum(max float64, exclusive bool) *Schema {
   394  	s.Maximum = &max
   395  	s.ExclusiveMaximum = exclusive
   396  	return s
   397  }
   398  
   399  // WithMinimum sets a minimum number value
   400  func (s *Schema) WithMinimum(min float64, exclusive bool) *Schema {
   401  	s.Minimum = &min
   402  	s.ExclusiveMinimum = exclusive
   403  	return s
   404  }
   405  
   406  // WithEnum sets a the enum values (replace)
   407  func (s *Schema) WithEnum(values ...interface{}) *Schema {
   408  	s.Enum = append([]interface{}{}, values...)
   409  	return s
   410  }
   411  
   412  // WithMaxItems sets the max items
   413  func (s *Schema) WithMaxItems(size int64) *Schema {
   414  	s.MaxItems = &size
   415  	return s
   416  }
   417  
   418  // WithMinItems sets the min items
   419  func (s *Schema) WithMinItems(size int64) *Schema {
   420  	s.MinItems = &size
   421  	return s
   422  }
   423  
   424  // UniqueValues dictates that this array can only have unique items
   425  func (s *Schema) UniqueValues() *Schema {
   426  	s.UniqueItems = true
   427  	return s
   428  }
   429  
   430  // AllowDuplicates this array can have duplicates
   431  func (s *Schema) AllowDuplicates() *Schema {
   432  	s.UniqueItems = false
   433  	return s
   434  }
   435  
   436  // AddToAllOf adds a schema to the allOf property
   437  func (s *Schema) AddToAllOf(schemas ...Schema) *Schema {
   438  	s.AllOf = append(s.AllOf, schemas...)
   439  	return s
   440  }
   441  
   442  // WithDiscriminator sets the name of the discriminator field
   443  func (s *Schema) WithDiscriminator(discriminator string) *Schema {
   444  	s.Discriminator = discriminator
   445  	return s
   446  }
   447  
   448  // AsReadOnly flags this schema as readonly
   449  func (s *Schema) AsReadOnly() *Schema {
   450  	s.ReadOnly = true
   451  	return s
   452  }
   453  
   454  // AsWritable flags this schema as writeable (not read-only)
   455  func (s *Schema) AsWritable() *Schema {
   456  	s.ReadOnly = false
   457  	return s
   458  }
   459  
   460  // WithExample sets the example for this schema
   461  func (s *Schema) WithExample(example interface{}) *Schema {
   462  	s.Example = example
   463  	return s
   464  }
   465  
   466  // WithExternalDocs sets/removes the external docs for/from this schema.
   467  // When you pass empty strings as params the external documents will be removed.
   468  // When you pass non-empty string as one value then those values will be used on the external docs object.
   469  // So when you pass a non-empty description, you should also pass the url and vice versa.
   470  func (s *Schema) WithExternalDocs(description, url string) *Schema {
   471  	if description == "" && url == "" {
   472  		s.ExternalDocs = nil
   473  		return s
   474  	}
   475  
   476  	if s.ExternalDocs == nil {
   477  		s.ExternalDocs = &ExternalDocumentation{}
   478  	}
   479  	s.ExternalDocs.Description = description
   480  	s.ExternalDocs.URL = url
   481  	return s
   482  }
   483  
   484  // MarshalJSON marshal this to JSON
   485  func (s Schema) MarshalJSON() ([]byte, error) {
   486  	if internal.UseOptimizedJSONMarshaling {
   487  		return internal.DeterministicMarshal(s)
   488  	}
   489  	b1, err := json.Marshal(s.SchemaProps)
   490  	if err != nil {
   491  		return nil, fmt.Errorf("schema props %v", err)
   492  	}
   493  	b2, err := json.Marshal(s.VendorExtensible)
   494  	if err != nil {
   495  		return nil, fmt.Errorf("vendor props %v", err)
   496  	}
   497  	b3, err := s.Ref.MarshalJSON()
   498  	if err != nil {
   499  		return nil, fmt.Errorf("ref prop %v", err)
   500  	}
   501  	b4, err := s.Schema.MarshalJSON()
   502  	if err != nil {
   503  		return nil, fmt.Errorf("schema prop %v", err)
   504  	}
   505  	b5, err := json.Marshal(s.SwaggerSchemaProps)
   506  	if err != nil {
   507  		return nil, fmt.Errorf("common validations %v", err)
   508  	}
   509  	var b6 []byte
   510  	if s.ExtraProps != nil {
   511  		jj, err := json.Marshal(s.ExtraProps)
   512  		if err != nil {
   513  			return nil, fmt.Errorf("extra props %v", err)
   514  		}
   515  		b6 = jj
   516  	}
   517  	return swag.ConcatJSON(b1, b2, b3, b4, b5, b6), nil
   518  }
   519  
   520  func (s Schema) MarshalNextJSON(opts jsonv2.MarshalOptions, enc *jsonv2.Encoder) error {
   521  	type ArbitraryKeys map[string]interface{}
   522  	var x struct {
   523  		ArbitraryKeys
   524  		SchemaProps        schemaPropsOmitZero        `json:",inline"`
   525  		SwaggerSchemaProps swaggerSchemaPropsOmitZero `json:",inline"`
   526  		Schema             string                     `json:"$schema,omitempty"`
   527  		Ref                string                     `json:"$ref,omitempty"`
   528  	}
   529  	x.ArbitraryKeys = make(map[string]any, len(s.Extensions)+len(s.ExtraProps))
   530  	for k, v := range s.Extensions {
   531  		if internal.IsExtensionKey(k) {
   532  			x.ArbitraryKeys[k] = v
   533  		}
   534  	}
   535  	for k, v := range s.ExtraProps {
   536  		x.ArbitraryKeys[k] = v
   537  	}
   538  	x.SchemaProps = schemaPropsOmitZero(s.SchemaProps)
   539  	x.SwaggerSchemaProps = swaggerSchemaPropsOmitZero(s.SwaggerSchemaProps)
   540  	x.Ref = s.Ref.String()
   541  	x.Schema = string(s.Schema)
   542  	return opts.MarshalNext(enc, x)
   543  }
   544  
   545  // UnmarshalJSON marshal this from JSON
   546  func (s *Schema) UnmarshalJSON(data []byte) error {
   547  	if internal.UseOptimizedJSONUnmarshaling {
   548  		return jsonv2.Unmarshal(data, s)
   549  	}
   550  
   551  	props := struct {
   552  		SchemaProps
   553  		SwaggerSchemaProps
   554  	}{}
   555  	if err := json.Unmarshal(data, &props); err != nil {
   556  		return err
   557  	}
   558  
   559  	sch := Schema{
   560  		SchemaProps:        props.SchemaProps,
   561  		SwaggerSchemaProps: props.SwaggerSchemaProps,
   562  	}
   563  
   564  	var d map[string]interface{}
   565  	if err := json.Unmarshal(data, &d); err != nil {
   566  		return err
   567  	}
   568  
   569  	_ = sch.Ref.fromMap(d)
   570  	_ = sch.Schema.fromMap(d)
   571  
   572  	delete(d, "$ref")
   573  	delete(d, "$schema")
   574  	for _, pn := range swag.DefaultJSONNameProvider.GetJSONNames(s) {
   575  		delete(d, pn)
   576  	}
   577  
   578  	for k, vv := range d {
   579  		lk := strings.ToLower(k)
   580  		if strings.HasPrefix(lk, "x-") {
   581  			if sch.Extensions == nil {
   582  				sch.Extensions = map[string]interface{}{}
   583  			}
   584  			sch.Extensions[k] = vv
   585  			continue
   586  		}
   587  		if sch.ExtraProps == nil {
   588  			sch.ExtraProps = map[string]interface{}{}
   589  		}
   590  		sch.ExtraProps[k] = vv
   591  	}
   592  
   593  	*s = sch
   594  
   595  	return nil
   596  }
   597  
   598  func (s *Schema) UnmarshalNextJSON(opts jsonv2.UnmarshalOptions, dec *jsonv2.Decoder) error {
   599  	var x struct {
   600  		Extensions
   601  		SchemaProps
   602  		SwaggerSchemaProps
   603  	}
   604  	if err := opts.UnmarshalNext(dec, &x); err != nil {
   605  		return err
   606  	}
   607  
   608  	if err := x.Ref.fromMap(x.Extensions); err != nil {
   609  		return err
   610  	}
   611  
   612  	if err := x.Schema.fromMap(x.Extensions); err != nil {
   613  		return err
   614  	}
   615  
   616  	delete(x.Extensions, "$ref")
   617  	delete(x.Extensions, "$schema")
   618  
   619  	for _, pn := range swag.DefaultJSONNameProvider.GetJSONNames(s) {
   620  		delete(x.Extensions, pn)
   621  	}
   622  	if len(x.Extensions) == 0 {
   623  		x.Extensions = nil
   624  	}
   625  
   626  	s.ExtraProps = x.Extensions.sanitizeWithExtra()
   627  	s.Extensions = internal.SanitizeExtensions(x.Extensions)
   628  	s.SchemaProps = x.SchemaProps
   629  	s.SwaggerSchemaProps = x.SwaggerSchemaProps
   630  	return nil
   631  }