-
Couldn't load subscription status.
- Fork 118
Description
With the following json schema, useRefAllOf is expected to apply minItems: 1 and maxItems: 5, and useOnlyRef is expected to apply only minItems: 1.
In practice, however, useOnlyRef also applies minItems: 1 and maxItems: 5.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"arrayMin1": {
"type": "object",
"additionalProperties": false,
"properties": {
"items": {
"type": "array",
"minItems": 1
}
}
}
},
"type": "object",
"additionalProperties": false,
"properties": {
"useRefAllOf": {
"allOf": [
{
"$ref": "#/definitions/arrayMin1"
},
{
"type": "object",
"properties": {
"items": {
"type": "array",
"maxItems": 5
}
}
}
]
},
"useOnlyRef": {
"$ref": "#/definitions/arrayMin1"
},
"noUseRefAllOf1": {
"allOf": [
{
"type": "object",
"properties": {
"items": {
"type": "array",
"minItems": 1
}
}
},
{
"type": "object",
"properties": {
"items": {
"type": "array",
"maxItems": 5
}
}
}
]
},
"noUseRefAllOf2": {
"allOf": [
{
"type": "object",
"properties": {
"items": {
"type": "array",
"minItems": 1
}
}
},
{
"type": "object",
"properties": {
"items": {
"type": "array",
"maxItems": 2
}
}
}
]
}
}
}- output schema
// Code generated by github.com/atombender/go-jsonschema, DO NOT EDIT.
package entity
import "encoding/json"
import "fmt"
type ArrayMin1 struct {
// Items corresponds to the JSON schema field "items".
Items []interface{} `json:"items,omitempty" yaml:"items,omitempty" mapstructure:"items,omitempty"`
}
// UnmarshalJSON implements json.Unmarshaler.
func (j *ArrayMin1) UnmarshalJSON(value []byte) error {
type Plain ArrayMin1
var plain Plain
if err := json.Unmarshal(value, &plain); err != nil {
return err
}
if plain.Items != nil && len(plain.Items) < 1 {
return fmt.Errorf("field %s length: must be >= %d", "items", 1)
}
*j = ArrayMin1(plain)
return nil
}
type HelmChartValues struct {
// NoUseRefAllOf1 corresponds to the JSON schema field "noUseRefAllOf1".
NoUseRefAllOf1 *HelmChartValuesNoUseRefAllOf1 `json:"noUseRefAllOf1,omitempty" yaml:"noUseRefAllOf1,omitempty" mapstructure:"noUseRefAllOf1,omitempty"`
// NoUseRefAllOf2 corresponds to the JSON schema field "noUseRefAllOf2".
NoUseRefAllOf2 *HelmChartValuesNoUseRefAllOf2 `json:"noUseRefAllOf2,omitempty" yaml:"noUseRefAllOf2,omitempty" mapstructure:"noUseRefAllOf2,omitempty"`
// UseOnlyRef corresponds to the JSON schema field "useOnlyRef".
UseOnlyRef *ArrayMin1 `json:"useOnlyRef,omitempty" yaml:"useOnlyRef,omitempty" mapstructure:"useOnlyRef,omitempty"`
// UseRefAllOf corresponds to the JSON schema field "useRefAllOf".
UseRefAllOf *HelmChartValuesUseRefAllOf `json:"useRefAllOf,omitempty" yaml:"useRefAllOf,omitempty" mapstructure:"useRefAllOf,omitempty"`
}
type HelmChartValuesNoUseRefAllOf1 struct {
// Items corresponds to the JSON schema field "items".
Items []interface{} `json:"items,omitempty" yaml:"items,omitempty" mapstructure:"items,omitempty"`
}
// UnmarshalJSON implements json.Unmarshaler.
func (j *HelmChartValuesNoUseRefAllOf1) UnmarshalJSON(value []byte) error {
type Plain HelmChartValuesNoUseRefAllOf1
var plain Plain
if err := json.Unmarshal(value, &plain); err != nil {
return err
}
if plain.Items != nil && len(plain.Items) < 1 {
return fmt.Errorf("field %s length: must be >= %d", "items", 1)
}
if len(plain.Items) > 5 {
return fmt.Errorf("field %s length: must be <= %d", "items", 5)
}
*j = HelmChartValuesNoUseRefAllOf1(plain)
return nil
}
type HelmChartValuesNoUseRefAllOf2 struct {
// Items corresponds to the JSON schema field "items".
Items []interface{} `json:"items,omitempty" yaml:"items,omitempty" mapstructure:"items,omitempty"`
}
// UnmarshalJSON implements json.Unmarshaler.
func (j *HelmChartValuesNoUseRefAllOf2) UnmarshalJSON(value []byte) error {
type Plain HelmChartValuesNoUseRefAllOf2
var plain Plain
if err := json.Unmarshal(value, &plain); err != nil {
return err
}
if plain.Items != nil && len(plain.Items) < 1 {
return fmt.Errorf("field %s length: must be >= %d", "items", 1)
}
if len(plain.Items) > 2 {
return fmt.Errorf("field %s length: must be <= %d", "items", 2)
}
*j = HelmChartValuesNoUseRefAllOf2(plain)
return nil
}
type HelmChartValuesUseRefAllOf struct {
// Items corresponds to the JSON schema field "items".
Items []interface{} `json:"items,omitempty" yaml:"items,omitempty" mapstructure:"items,omitempty"`
}
// UnmarshalJSON implements json.Unmarshaler.
func (j *HelmChartValuesUseRefAllOf) UnmarshalJSON(value []byte) error {
type Plain HelmChartValuesUseRefAllOf
var plain Plain
if err := json.Unmarshal(value, &plain); err != nil {
return err
}
if plain.Items != nil && len(plain.Items) < 1 {
return fmt.Errorf("field %s length: must be >= %d", "items", 1)
}
if len(plain.Items) > 5 {
return fmt.Errorf("field %s length: must be <= %d", "items", 5)
}
*j = HelmChartValuesUseRefAllOf(plain)
return nil
}I think the reason for this is that when ref is included in allOf, schema merge is performed on the Properties map pointer value of the referring ref schema when schema merge is performed.
As a result, allOf will affect all schemas that reference the same ref.
https://github.com/omissis/go-jsonschema/blob/main/pkg/schemas/model.go#L275
https://github.com/omissis/go-jsonschema/blob/main/pkg/schemas/model.go#L315
I think you need to deep copy the pointer in the map before merge.