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