Skip to content

Commit 66a9d04

Browse files
baywetCopilot
andcommitted
feat(library): support schema keywords on references
Add JSON Schema keyword sibling storage, parsing, accessors, and serialization for schema references across OpenAPI 3.0 extension compatibility and OpenAPI 3.1+ native keywords. Fixes #2903 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 26c2358 commit 66a9d04

9 files changed

Lines changed: 1115 additions & 94 deletions

src/Microsoft.OpenApi/Models/JsonSchemaReference.cs

Lines changed: 572 additions & 1 deletion
Large diffs are not rendered by default.

src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs

Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -49,43 +49,43 @@ public string? Title
4949
set => Reference.Title = value;
5050
}
5151
/// <inheritdoc/>
52-
public Uri? Schema { get => Reference.Schema ?? Target?.Schema; }
52+
public Uri? Schema { get => Reference.Schema ?? Target?.Schema; set => Reference.Schema = value; }
5353
/// <inheritdoc/>
54-
public string? Id { get => string.IsNullOrEmpty(Reference.SchemaId) ? Target?.Id : Reference.SchemaId; }
54+
public string? Id { get => string.IsNullOrEmpty(Reference.SchemaId) ? Target?.Id : Reference.SchemaId; set => Reference.SchemaId = value; }
5555
/// <inheritdoc/>
56-
public string? Comment { get => string.IsNullOrEmpty(Reference.Comment) ? Target?.Comment : Reference.Comment; }
56+
public string? Comment { get => string.IsNullOrEmpty(Reference.Comment) ? Target?.Comment : Reference.Comment; set => Reference.Comment = value; }
5757
/// <inheritdoc/>
58-
public IDictionary<string, bool>? Vocabulary { get => Reference.Vocabulary ?? Target?.Vocabulary; }
58+
public IDictionary<string, bool>? Vocabulary { get => Reference.Vocabulary ?? Target?.Vocabulary; set => Reference.Vocabulary = value; }
5959
/// <inheritdoc/>
60-
public string? DynamicRef { get => string.IsNullOrEmpty(Reference.DynamicRef) ? Target?.DynamicRef : Reference.DynamicRef; }
60+
public string? DynamicRef { get => string.IsNullOrEmpty(Reference.DynamicRef) ? Target?.DynamicRef : Reference.DynamicRef; set => Reference.DynamicRef = value; }
6161
/// <inheritdoc/>
62-
public string? DynamicAnchor { get => string.IsNullOrEmpty(Reference.DynamicAnchor) ? Target?.DynamicAnchor : Reference.DynamicAnchor; }
62+
public string? DynamicAnchor { get => string.IsNullOrEmpty(Reference.DynamicAnchor) ? Target?.DynamicAnchor : Reference.DynamicAnchor; set => Reference.DynamicAnchor = value; }
6363
/// <inheritdoc/>
64-
public IDictionary<string, IOpenApiSchema>? Definitions { get => Reference.Definitions ?? Target?.Definitions; }
64+
public IDictionary<string, IOpenApiSchema>? Definitions { get => Reference.Definitions ?? Target?.Definitions; set => Reference.Definitions = value; }
6565
/// <inheritdoc/>
66-
public string? Anchor { get => string.IsNullOrEmpty(Reference.Anchor) ? (Target as IOpenApiSchemaMissingProperties)?.Anchor : Reference.Anchor; }
66+
public string? Anchor { get => string.IsNullOrEmpty(Reference.Anchor) ? (Target as IOpenApiSchemaMissingProperties)?.Anchor : Reference.Anchor; set => Reference.Anchor = value; }
6767
/// <inheritdoc/>
68-
public string? ExclusiveMaximum { get => Target?.ExclusiveMaximum; }
68+
public string? ExclusiveMaximum { get => string.IsNullOrEmpty(Reference.ExclusiveMaximum) ? Target?.ExclusiveMaximum : Reference.ExclusiveMaximum; set => Reference.ExclusiveMaximum = value; }
6969
/// <inheritdoc/>
70-
public string? ExclusiveMinimum { get => Target?.ExclusiveMinimum; }
70+
public string? ExclusiveMinimum { get => string.IsNullOrEmpty(Reference.ExclusiveMinimum) ? Target?.ExclusiveMinimum : Reference.ExclusiveMinimum; set => Reference.ExclusiveMinimum = value; }
7171
/// <inheritdoc/>
72-
public JsonSchemaType? Type { get => Target?.Type; }
72+
public JsonSchemaType? Type { get => Reference.SchemaType ?? Target?.Type; set => Reference.SchemaType = value; }
7373
/// <inheritdoc/>
74-
public string? Const { get => Target?.Const; }
74+
public string? Const { get => string.IsNullOrEmpty(Reference.Const) ? Target?.Const : Reference.Const; set => Reference.Const = value; }
7575
/// <inheritdoc/>
76-
public string? Format { get => Target?.Format; }
76+
public string? Format { get => string.IsNullOrEmpty(Reference.Format) ? Target?.Format : Reference.Format; set => Reference.Format = value; }
7777
/// <inheritdoc/>
78-
public string? Maximum { get => Target?.Maximum; }
78+
public string? Maximum { get => string.IsNullOrEmpty(Reference.Maximum) ? Target?.Maximum : Reference.Maximum; set => Reference.Maximum = value; }
7979
/// <inheritdoc/>
80-
public string? Minimum { get => Target?.Minimum; }
80+
public string? Minimum { get => string.IsNullOrEmpty(Reference.Minimum) ? Target?.Minimum : Reference.Minimum; set => Reference.Minimum = value; }
8181
/// <inheritdoc/>
82-
public int? MaxLength { get => Target?.MaxLength; }
82+
public int? MaxLength { get => Reference.MaxLength ?? Target?.MaxLength; set => Reference.MaxLength = value; }
8383
/// <inheritdoc/>
84-
public int? MinLength { get => Target?.MinLength; }
84+
public int? MinLength { get => Reference.MinLength ?? Target?.MinLength; set => Reference.MinLength = value; }
8585
/// <inheritdoc/>
86-
public string? Pattern { get => Target?.Pattern; }
86+
public string? Pattern { get => string.IsNullOrEmpty(Reference.Pattern) ? Target?.Pattern : Reference.Pattern; set => Reference.Pattern = value; }
8787
/// <inheritdoc/>
88-
public decimal? MultipleOf { get => Target?.MultipleOf; }
88+
public decimal? MultipleOf { get => Reference.MultipleOf ?? Target?.MultipleOf; set => Reference.MultipleOf = value; }
8989
/// <inheritdoc/>
9090
public JsonNode? Default
9191
{
@@ -105,83 +105,83 @@ public bool WriteOnly
105105
set => Reference.WriteOnly = value;
106106
}
107107
/// <inheritdoc/>
108-
public IList<IOpenApiSchema>? AllOf { get => Target?.AllOf; }
108+
public IList<IOpenApiSchema>? AllOf { get => Reference.AllOf ?? Target?.AllOf; set => Reference.AllOf = value; }
109109
/// <inheritdoc/>
110-
public IList<IOpenApiSchema>? OneOf { get => Target?.OneOf; }
110+
public IList<IOpenApiSchema>? OneOf { get => Reference.OneOf ?? Target?.OneOf; set => Reference.OneOf = value; }
111111
/// <inheritdoc/>
112-
public IList<IOpenApiSchema>? AnyOf { get => Target?.AnyOf; }
112+
public IList<IOpenApiSchema>? AnyOf { get => Reference.AnyOf ?? Target?.AnyOf; set => Reference.AnyOf = value; }
113113
/// <inheritdoc/>
114-
public IOpenApiSchema? Not { get => Target?.Not; }
114+
public IOpenApiSchema? Not { get => Reference.Not ?? Target?.Not; set => Reference.Not = value; }
115115
/// <inheritdoc/>
116-
public ISet<string>? Required { get => Target?.Required; }
116+
public ISet<string>? Required { get => Reference.Required ?? Target?.Required; set => Reference.Required = value; }
117117
/// <inheritdoc/>
118-
public IOpenApiSchema? Items { get => Target?.Items; }
118+
public IOpenApiSchema? Items { get => Reference.Items ?? Target?.Items; set => Reference.Items = value; }
119119
/// <inheritdoc/>
120-
public int? MaxItems { get => Target?.MaxItems; }
120+
public int? MaxItems { get => Reference.MaxItems ?? Target?.MaxItems; set => Reference.MaxItems = value; }
121121
/// <inheritdoc/>
122-
public int? MinItems { get => Target?.MinItems; }
122+
public int? MinItems { get => Reference.MinItems ?? Target?.MinItems; set => Reference.MinItems = value; }
123123
/// <inheritdoc/>
124-
public bool? UniqueItems { get => Target?.UniqueItems; }
124+
public bool? UniqueItems { get => Reference.UniqueItems ?? Target?.UniqueItems; set => Reference.UniqueItems = value; }
125125
/// <inheritdoc/>
126-
public IOpenApiSchema? Contains { get => (Target as IOpenApiSchemaMissingProperties)?.Contains; }
126+
public IOpenApiSchema? Contains { get => Reference.Contains ?? (Target as IOpenApiSchemaMissingProperties)?.Contains; set => Reference.Contains = value; }
127127
/// <inheritdoc/>
128-
public uint? MaxContains { get => (Target as IOpenApiSchemaMissingProperties)?.MaxContains; }
128+
public uint? MaxContains { get => Reference.MaxContains ?? (Target as IOpenApiSchemaMissingProperties)?.MaxContains; set => Reference.MaxContains = value; }
129129
/// <inheritdoc/>
130-
public uint? MinContains { get => (Target as IOpenApiSchemaMissingProperties)?.MinContains; }
130+
public uint? MinContains { get => Reference.MinContains ?? (Target as IOpenApiSchemaMissingProperties)?.MinContains; set => Reference.MinContains = value; }
131131
/// <inheritdoc/>
132-
public IDictionary<string, IOpenApiSchema>? Properties { get => Target?.Properties; }
132+
public IDictionary<string, IOpenApiSchema>? Properties { get => Reference.Properties ?? Target?.Properties; set => Reference.Properties = value; }
133133
/// <inheritdoc/>
134-
public IDictionary<string, IOpenApiSchema>? PatternProperties { get => Target?.PatternProperties; }
134+
public IDictionary<string, IOpenApiSchema>? PatternProperties { get => Reference.PatternProperties ?? Target?.PatternProperties; set => Reference.PatternProperties = value; }
135135
/// <inheritdoc/>
136-
public int? MaxProperties { get => Target?.MaxProperties; }
136+
public int? MaxProperties { get => Reference.MaxProperties ?? Target?.MaxProperties; set => Reference.MaxProperties = value; }
137137
/// <inheritdoc/>
138-
public int? MinProperties { get => Target?.MinProperties; }
138+
public int? MinProperties { get => Reference.MinProperties ?? Target?.MinProperties; set => Reference.MinProperties = value; }
139139
/// <inheritdoc/>
140-
public bool AdditionalPropertiesAllowed { get => Target?.AdditionalPropertiesAllowed ?? true; }
140+
public bool AdditionalPropertiesAllowed { get => Reference.AdditionalPropertiesAllowed ?? Target?.AdditionalPropertiesAllowed ?? true; set => Reference.AdditionalPropertiesAllowed = value; }
141141
/// <inheritdoc/>
142-
public IOpenApiSchema? AdditionalProperties { get => Target?.AdditionalProperties; }
142+
public IOpenApiSchema? AdditionalProperties { get => Reference.AdditionalProperties ?? Target?.AdditionalProperties; set => Reference.AdditionalProperties = value; }
143143
/// <inheritdoc/>
144-
public OpenApiDiscriminator? Discriminator { get => Target?.Discriminator; }
144+
public OpenApiDiscriminator? Discriminator { get => Reference.Discriminator ?? Target?.Discriminator; set => Reference.Discriminator = value; }
145145
/// <inheritdoc/>
146-
public JsonNode? Example { get => Target?.Example; }
146+
public JsonNode? Example { get => Reference.Example ?? Target?.Example; set => Reference.Example = value; }
147147
/// <inheritdoc/>
148148
public IList<JsonNode>? Examples
149149
{
150150
get => Reference.Examples ?? Target?.Examples;
151151
set => Reference.Examples = value;
152152
}
153153
/// <inheritdoc/>
154-
public IList<JsonNode>? Enum { get => Target?.Enum; }
154+
public IList<JsonNode>? Enum { get => Reference.Enum ?? Target?.Enum; set => Reference.Enum = value; }
155155
/// <inheritdoc/>
156-
public bool UnevaluatedProperties { get => Target?.UnevaluatedProperties ?? true; }
156+
public bool UnevaluatedProperties { get => Reference.UnevaluatedProperties ?? Target?.UnevaluatedProperties ?? true; set => Reference.UnevaluatedProperties = value; }
157157
/// <inheritdoc/>
158-
public IOpenApiSchema? UnevaluatedPropertiesSchema { get => (Target as IOpenApiSchemaMissingProperties)?.UnevaluatedPropertiesSchema; }
158+
public IOpenApiSchema? UnevaluatedPropertiesSchema { get => Reference.UnevaluatedPropertiesSchema ?? (Target as IOpenApiSchemaMissingProperties)?.UnevaluatedPropertiesSchema; set => Reference.UnevaluatedPropertiesSchema = value; }
159159
/// <inheritdoc/>
160-
public string? ContentEncoding { get => (Target as IOpenApiSchemaMissingProperties)?.ContentEncoding; }
160+
public string? ContentEncoding { get => string.IsNullOrEmpty(Reference.ContentEncoding) ? (Target as IOpenApiSchemaMissingProperties)?.ContentEncoding : Reference.ContentEncoding; set => Reference.ContentEncoding = value; }
161161
/// <inheritdoc/>
162-
public string? ContentMediaType { get => (Target as IOpenApiSchemaMissingProperties)?.ContentMediaType; }
162+
public string? ContentMediaType { get => string.IsNullOrEmpty(Reference.ContentMediaType) ? (Target as IOpenApiSchemaMissingProperties)?.ContentMediaType : Reference.ContentMediaType; set => Reference.ContentMediaType = value; }
163163
/// <inheritdoc/>
164-
public IOpenApiSchema? ContentSchema { get => (Target as IOpenApiSchemaMissingProperties)?.ContentSchema; }
164+
public IOpenApiSchema? ContentSchema { get => Reference.ContentSchema ?? (Target as IOpenApiSchemaMissingProperties)?.ContentSchema; set => Reference.ContentSchema = value; }
165165
/// <inheritdoc/>
166-
public IOpenApiSchema? PropertyNames { get => (Target as IOpenApiSchemaMissingProperties)?.PropertyNames; }
166+
public IOpenApiSchema? PropertyNames { get => Reference.PropertyNames ?? (Target as IOpenApiSchemaMissingProperties)?.PropertyNames; set => Reference.PropertyNames = value; }
167167
/// <inheritdoc/>
168-
public IDictionary<string, IOpenApiSchema>? DependentSchemas { get => (Target as IOpenApiSchemaMissingProperties)?.DependentSchemas; }
168+
public IDictionary<string, IOpenApiSchema>? DependentSchemas { get => Reference.DependentSchemas ?? (Target as IOpenApiSchemaMissingProperties)?.DependentSchemas; set => Reference.DependentSchemas = value; }
169169
/// <inheritdoc/>
170-
public IOpenApiSchema? If { get => (Target as IOpenApiSchemaMissingProperties)?.If; }
170+
public IOpenApiSchema? If { get => Reference.If ?? (Target as IOpenApiSchemaMissingProperties)?.If; set => Reference.If = value; }
171171
/// <inheritdoc/>
172-
public IOpenApiSchema? Then { get => (Target as IOpenApiSchemaMissingProperties)?.Then; }
172+
public IOpenApiSchema? Then { get => Reference.Then ?? (Target as IOpenApiSchemaMissingProperties)?.Then; set => Reference.Then = value; }
173173
/// <inheritdoc/>
174-
public IOpenApiSchema? Else { get => (Target as IOpenApiSchemaMissingProperties)?.Else; }
174+
public IOpenApiSchema? Else { get => Reference.Else ?? (Target as IOpenApiSchemaMissingProperties)?.Else; set => Reference.Else = value; }
175175
/// <inheritdoc/>
176-
public OpenApiExternalDocs? ExternalDocs { get => Target?.ExternalDocs; }
176+
public OpenApiExternalDocs? ExternalDocs { get => Reference.ExternalDocs ?? Target?.ExternalDocs; set => Reference.ExternalDocs = value; }
177177
/// <inheritdoc/>
178178
public bool Deprecated
179179
{
180180
get => Reference.Deprecated ?? Target?.Deprecated ?? false;
181181
set => Reference.Deprecated = value;
182182
}
183183
/// <inheritdoc/>
184-
public OpenApiXml? Xml { get => Target?.Xml; }
184+
public OpenApiXml? Xml { get => Reference.Xml ?? Target?.Xml; set => Reference.Xml = value; }
185185
/// <inheritdoc/>
186186
public IDictionary<string, IOpenApiExtension>? Extensions
187187
{
@@ -190,10 +190,10 @@ public IDictionary<string, IOpenApiExtension>? Extensions
190190
}
191191

192192
/// <inheritdoc/>
193-
public IDictionary<string, JsonNode>? UnrecognizedKeywords { get => Target?.UnrecognizedKeywords; }
193+
public IDictionary<string, JsonNode>? UnrecognizedKeywords { get => Reference.UnrecognizedKeywords ?? Target?.UnrecognizedKeywords; set => Reference.UnrecognizedKeywords = value; }
194194

195195
/// <inheritdoc/>
196-
public IDictionary<string, HashSet<string>>? DependentRequired { get => Target?.DependentRequired; }
196+
public IDictionary<string, HashSet<string>>? DependentRequired { get => Reference.DependentRequired ?? Target?.DependentRequired; set => Reference.DependentRequired = value; }
197197

198198
/// <inheritdoc/>
199199
public override void SerializeAsV31(IOpenApiWriter writer)
@@ -251,6 +251,6 @@ protected override JsonSchemaReference CopyReference(JsonSchemaReference sourceR
251251
{
252252
return new JsonSchemaReference(sourceReference);
253253
}
254-
#pragma warning restore CS0618
254+
#pragma warning restore CS0618
255255
}
256256
}

0 commit comments

Comments
 (0)