Skip to content

Commit 10cde39

Browse files
Copilotbaywet
andcommitted
Refactor schema metadata annotations to separate class per review feedback
Co-authored-by: baywet <[email protected]>
1 parent 66ccf74 commit 10cde39

File tree

4 files changed

+233
-123
lines changed

4 files changed

+233
-123
lines changed

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"sdk": {
3-
"version": "8.0.115"
3+
"version": "8.0.406"
44
}
55
}

src/Microsoft.OpenApi/Models/OpenApiReference.cs

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -27,41 +27,7 @@ public class OpenApiReference : IOpenApiSerializable, IOpenApiDescribedElement,
2727
/// </summary>
2828
public string? Description { get; set; }
2929

30-
/// <summary>
31-
/// A default value which by default SHOULD override that of the referenced component.
32-
/// If the referenced object-type does not allow a default field, then this field has no effect.
33-
/// </summary>
34-
public JsonNode? Default { get; set; }
35-
36-
/// <summary>
37-
/// A title which by default SHOULD override that of the referenced component.
38-
/// If the referenced object-type does not allow a title field, then this field has no effect.
39-
/// </summary>
40-
public string? Title { get; set; }
41-
42-
/// <summary>
43-
/// Indicates whether the referenced component is deprecated.
44-
/// If the referenced object-type does not allow a deprecated field, then this field has no effect.
45-
/// </summary>
46-
public bool? Deprecated { get; set; }
47-
48-
/// <summary>
49-
/// Indicates whether the referenced component is read-only.
50-
/// If the referenced object-type does not allow a readOnly field, then this field has no effect.
51-
/// </summary>
52-
public bool? ReadOnly { get; set; }
5330

54-
/// <summary>
55-
/// Indicates whether the referenced component is write-only.
56-
/// If the referenced object-type does not allow a writeOnly field, then this field has no effect.
57-
/// </summary>
58-
public bool? WriteOnly { get; set; }
59-
60-
/// <summary>
61-
/// Example values which by default SHOULD override those of the referenced component.
62-
/// If the referenced object-type does not allow examples, then this field has no effect.
63-
/// </summary>
64-
public IList<JsonNode>? Examples { get; set; }
6531

6632
/// <summary>
6733
/// External resource in the reference.
@@ -190,12 +156,6 @@ public OpenApiReference(OpenApiReference reference)
190156
Utils.CheckArgumentNull(reference);
191157
Summary = reference.Summary;
192158
Description = reference.Description;
193-
Default = reference.Default;
194-
Title = reference.Title;
195-
Deprecated = reference.Deprecated;
196-
ReadOnly = reference.ReadOnly;
197-
WriteOnly = reference.WriteOnly;
198-
Examples = reference.Examples;
199159
ExternalResource = reference.ExternalResource;
200160
Type = reference.Type;
201161
Id = reference.Id;
@@ -212,17 +172,6 @@ public void SerializeAsV31(IOpenApiWriter writer)
212172
// summary and description are in 3.1 but not in 3.0
213173
w.WriteProperty(OpenApiConstants.Summary, Summary);
214174
w.WriteProperty(OpenApiConstants.Description, Description);
215-
216-
// Additional schema metadata annotations in 3.1
217-
w.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d));
218-
w.WriteProperty(OpenApiConstants.Title, Title);
219-
w.WriteProperty(OpenApiConstants.Deprecated, Deprecated, false);
220-
w.WriteProperty(OpenApiConstants.ReadOnly, ReadOnly, false);
221-
w.WriteProperty(OpenApiConstants.WriteOnly, WriteOnly, false);
222-
if (Examples != null && Examples.Any())
223-
{
224-
w.WriteOptionalCollection(OpenApiConstants.Examples, Examples, (w, e) => w.WriteAny(e));
225-
}
226175
});
227176
}
228177

@@ -354,7 +303,6 @@ internal void SetMetadataFromMapNode(MapNode mapNode)
354303
// Summary and Description
355304
var description = GetPropertyValueFromNode(jsonObject, OpenApiConstants.Description);
356305
var summary = GetPropertyValueFromNode(jsonObject, OpenApiConstants.Summary);
357-
var title = GetPropertyValueFromNode(jsonObject, OpenApiConstants.Title);
358306

359307
if (!string.IsNullOrEmpty(description))
360308
{
@@ -364,54 +312,6 @@ internal void SetMetadataFromMapNode(MapNode mapNode)
364312
{
365313
Summary = summary;
366314
}
367-
if (!string.IsNullOrEmpty(title))
368-
{
369-
Title = title;
370-
}
371-
372-
// Boolean properties
373-
if (jsonObject.TryGetPropertyValue(OpenApiConstants.Deprecated, out var deprecatedNode) && deprecatedNode is JsonValue deprecatedValue)
374-
{
375-
if (deprecatedValue.TryGetValue<bool>(out var deprecated))
376-
{
377-
Deprecated = deprecated;
378-
}
379-
}
380-
381-
if (jsonObject.TryGetPropertyValue(OpenApiConstants.ReadOnly, out var readOnlyNode) && readOnlyNode is JsonValue readOnlyValue)
382-
{
383-
if (readOnlyValue.TryGetValue<bool>(out var readOnly))
384-
{
385-
ReadOnly = readOnly;
386-
}
387-
}
388-
389-
if (jsonObject.TryGetPropertyValue(OpenApiConstants.WriteOnly, out var writeOnlyNode) && writeOnlyNode is JsonValue writeOnlyValue)
390-
{
391-
if (writeOnlyValue.TryGetValue<bool>(out var writeOnly))
392-
{
393-
WriteOnly = writeOnly;
394-
}
395-
}
396-
397-
// Default value
398-
if (jsonObject.TryGetPropertyValue(OpenApiConstants.Default, out var defaultNode))
399-
{
400-
Default = defaultNode;
401-
}
402-
403-
// Examples
404-
if (jsonObject.TryGetPropertyValue(OpenApiConstants.Examples, out var examplesNode) && examplesNode is JsonArray examplesArray)
405-
{
406-
Examples = new List<JsonNode>();
407-
foreach (var example in examplesArray)
408-
{
409-
if (example != null)
410-
{
411-
Examples.Add(example);
412-
}
413-
}
414-
}
415315
}
416316

417317
internal void SetJsonPointerPath(string pointer, string nodeLocation)
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text.Json.Nodes;
7+
using Microsoft.OpenApi.Reader;
8+
9+
namespace Microsoft.OpenApi
10+
{
11+
/// <summary>
12+
/// Schema reference information that includes metadata annotations from JSON Schema 2020-12.
13+
/// This class extends OpenApiReference to provide schema-specific metadata override capabilities.
14+
/// </summary>
15+
public class OpenApiSchemaReferenceInformation : OpenApiReference
16+
{
17+
/// <summary>
18+
/// A default value which by default SHOULD override that of the referenced component.
19+
/// If the referenced object-type does not allow a default field, then this field has no effect.
20+
/// </summary>
21+
public JsonNode? Default { get; set; }
22+
23+
/// <summary>
24+
/// A title which by default SHOULD override that of the referenced component.
25+
/// If the referenced object-type does not allow a title field, then this field has no effect.
26+
/// </summary>
27+
public string? Title { get; set; }
28+
29+
/// <summary>
30+
/// Indicates whether the referenced component is deprecated.
31+
/// If the referenced object-type does not allow a deprecated field, then this field has no effect.
32+
/// </summary>
33+
public bool? Deprecated { get; set; }
34+
35+
/// <summary>
36+
/// Indicates whether the referenced component is read-only.
37+
/// If the referenced object-type does not allow a readOnly field, then this field has no effect.
38+
/// </summary>
39+
public bool? ReadOnly { get; set; }
40+
41+
/// <summary>
42+
/// Indicates whether the referenced component is write-only.
43+
/// If the referenced object-type does not allow a writeOnly field, then this field has no effect.
44+
/// </summary>
45+
public bool? WriteOnly { get; set; }
46+
47+
/// <summary>
48+
/// Example values which by default SHOULD override those of the referenced component.
49+
/// If the referenced object-type does not allow examples, then this field has no effect.
50+
/// </summary>
51+
public IList<JsonNode>? Examples { get; set; }
52+
53+
/// <summary>
54+
/// Parameterless constructor
55+
/// </summary>
56+
public OpenApiSchemaReferenceInformation() { }
57+
58+
/// <summary>
59+
/// Initializes a copy instance of the <see cref="OpenApiSchemaReferenceInformation"/> object
60+
/// </summary>
61+
public OpenApiSchemaReferenceInformation(OpenApiSchemaReferenceInformation reference) : base(reference)
62+
{
63+
Utils.CheckArgumentNull(reference);
64+
Default = reference.Default;
65+
Title = reference.Title;
66+
Deprecated = reference.Deprecated;
67+
ReadOnly = reference.ReadOnly;
68+
WriteOnly = reference.WriteOnly;
69+
Examples = reference.Examples;
70+
}
71+
72+
/// <summary>
73+
/// Serialize <see cref="OpenApiSchemaReferenceInformation"/> to Open Api v3.1.
74+
/// </summary>
75+
public new void SerializeAsV31(IOpenApiWriter writer)
76+
{
77+
Utils.CheckArgumentNull(writer);
78+
79+
if (Type == ReferenceType.Tag && !string.IsNullOrEmpty(ReferenceV3) && ReferenceV3 is not null)
80+
{
81+
// Write the string value only
82+
writer.WriteValue(ReferenceV3);
83+
return;
84+
}
85+
86+
writer.WriteStartObject();
87+
88+
// summary and description are in 3.1 but not in 3.0
89+
writer.WriteProperty(OpenApiConstants.Summary, Summary);
90+
writer.WriteProperty(OpenApiConstants.Description, Description);
91+
92+
// Additional schema metadata annotations in 3.1
93+
writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d));
94+
writer.WriteProperty(OpenApiConstants.Title, Title);
95+
if (Deprecated.HasValue)
96+
{
97+
writer.WriteProperty(OpenApiConstants.Deprecated, Deprecated.Value, false);
98+
}
99+
if (ReadOnly.HasValue)
100+
{
101+
writer.WriteProperty(OpenApiConstants.ReadOnly, ReadOnly.Value, false);
102+
}
103+
if (WriteOnly.HasValue)
104+
{
105+
writer.WriteProperty(OpenApiConstants.WriteOnly, WriteOnly.Value, false);
106+
}
107+
if (Examples != null && Examples.Any())
108+
{
109+
writer.WriteOptionalCollection(OpenApiConstants.Examples, Examples, (w, e) => w.WriteAny(e));
110+
}
111+
112+
// $ref
113+
writer.WriteProperty(OpenApiConstants.DollarRef, ReferenceV3);
114+
115+
writer.WriteEndObject();
116+
}
117+
118+
/// <summary>
119+
/// Sets metadata fields from a JSON node during parsing
120+
/// </summary>
121+
internal new void SetMetadataFromMapNode(MapNode mapNode)
122+
{
123+
base.SetMetadataFromMapNode(mapNode);
124+
125+
if (mapNode.JsonNode is not JsonObject jsonObject) return;
126+
127+
var title = GetPropertyValueFromNode(jsonObject, OpenApiConstants.Title);
128+
if (!string.IsNullOrEmpty(title))
129+
{
130+
Title = title;
131+
}
132+
133+
// Boolean properties
134+
if (jsonObject.TryGetPropertyValue(OpenApiConstants.Deprecated, out var deprecatedNode) && deprecatedNode is JsonValue deprecatedValue)
135+
{
136+
if (deprecatedValue.TryGetValue<bool>(out var deprecated))
137+
{
138+
Deprecated = deprecated;
139+
}
140+
}
141+
142+
if (jsonObject.TryGetPropertyValue(OpenApiConstants.ReadOnly, out var readOnlyNode) && readOnlyNode is JsonValue readOnlyValue)
143+
{
144+
if (readOnlyValue.TryGetValue<bool>(out var readOnly))
145+
{
146+
ReadOnly = readOnly;
147+
}
148+
}
149+
150+
if (jsonObject.TryGetPropertyValue(OpenApiConstants.WriteOnly, out var writeOnlyNode) && writeOnlyNode is JsonValue writeOnlyValue)
151+
{
152+
if (writeOnlyValue.TryGetValue<bool>(out var writeOnly))
153+
{
154+
WriteOnly = writeOnly;
155+
}
156+
}
157+
158+
// Default value
159+
if (jsonObject.TryGetPropertyValue(OpenApiConstants.Default, out var defaultNode))
160+
{
161+
Default = defaultNode;
162+
}
163+
164+
// Examples
165+
if (jsonObject.TryGetPropertyValue(OpenApiConstants.Examples, out var examplesNode) && examplesNode is JsonArray examplesArray)
166+
{
167+
Examples = new List<JsonNode>();
168+
foreach (var example in examplesArray)
169+
{
170+
if (example != null)
171+
{
172+
Examples.Add(example);
173+
}
174+
}
175+
}
176+
}
177+
178+
private static string? GetPropertyValueFromNode(JsonObject jsonObject, string key) =>
179+
jsonObject.TryGetPropertyValue(key, out var valueNode) && valueNode is JsonValue valueCast && valueCast.TryGetValue<string>(out var strValue) ? strValue : null;
180+
}
181+
}

0 commit comments

Comments
 (0)