Skip to content

Commit 5cfce6e

Browse files
committed
Add a V3 schema deserializer
1 parent f76fddf commit 5cfce6e

File tree

1 file changed

+202
-0
lines changed

1 file changed

+202
-0
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using Microsoft.OpenApi.Extensions;
5+
using Microsoft.OpenApi.Models;
6+
using Microsoft.OpenApi.Reader.ParseNodes;
7+
using Microsoft.OpenApi.Readers.ParseNodes;
8+
using System.Collections.Generic;
9+
using System.Globalization;
10+
11+
namespace Microsoft.OpenApi.Reader.V3
12+
{
13+
/// <summary>
14+
/// Class containing logic to deserialize Open API V3 document into
15+
/// runtime Open API object model.
16+
/// </summary>
17+
internal static partial class OpenApiV3Deserializer
18+
{
19+
private static readonly FixedFieldMap<OpenApiSchema> _openApiSchemaFixedFields = new()
20+
{
21+
{
22+
"title",
23+
(o, n, _) => o.Title = n.GetScalarValue()
24+
},
25+
{
26+
"multipleOf",
27+
(o, n, _) => o.MultipleOf = decimal.Parse(n.GetScalarValue(), NumberStyles.Float, CultureInfo.InvariantCulture)
28+
},
29+
{
30+
"maximum",
31+
(o, n, _) => o.Maximum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MaxValue)
32+
},
33+
{
34+
"exclusiveMaximum",
35+
(o, n, _) => o.ExclusiveMaximum = bool.Parse(n.GetScalarValue())
36+
},
37+
{
38+
"minimum",
39+
(o, n, _) => o.Minimum = ParserHelper.ParseDecimalWithFallbackOnOverflow(n.GetScalarValue(), decimal.MinValue)
40+
},
41+
{
42+
"exclusiveMinimum",
43+
(o, n, _) => o.ExclusiveMinimum = bool.Parse(n.GetScalarValue())
44+
},
45+
{
46+
"maxLength",
47+
(o, n, _) => o.MaxLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
48+
},
49+
{
50+
"minLength",
51+
(o, n, _) => o.MinLength = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
52+
},
53+
{
54+
"pattern",
55+
(o, n, _) => o.Pattern = n.GetScalarValue()
56+
},
57+
{
58+
"maxItems",
59+
(o, n, _) => o.MaxItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
60+
},
61+
{
62+
"minItems",
63+
(o, n, _) => o.MinItems = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
64+
},
65+
{
66+
"uniqueItems",
67+
(o, n, _) => o.UniqueItems = bool.Parse(n.GetScalarValue())
68+
},
69+
{
70+
"maxProperties",
71+
(o, n, _) => o.MaxProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
72+
},
73+
{
74+
"minProperties",
75+
(o, n, _) => o.MinProperties = int.Parse(n.GetScalarValue(), CultureInfo.InvariantCulture)
76+
},
77+
{
78+
"required",
79+
(o, n, _) => o.Required = new HashSet<string>(n.CreateSimpleList((n2, p) => n2.GetScalarValue()))
80+
},
81+
{
82+
"enum",
83+
(o, n, _) => o.Enum = n.CreateListOfAny()
84+
},
85+
{
86+
"type",
87+
(o, n, _) => o.Type = n.GetScalarValue()
88+
},
89+
{
90+
"allOf",
91+
(o, n, t) => o.AllOf = n.CreateList(LoadOpenApiSchema, t)
92+
},
93+
{
94+
"oneOf",
95+
(o, n, _) => o.OneOf = n.CreateList(LoadOpenApiSchema)
96+
},
97+
{
98+
"anyOf",
99+
(o, n, t) => o.AnyOf = n.CreateList(LoadOpenApiSchema, t)
100+
},
101+
{
102+
"not",
103+
(o, n, _) => o.Not = LoadOpenApiSchema(n)
104+
},
105+
{
106+
"items",
107+
(o, n, _) => o.Items = LoadOpenApiSchema(n)
108+
},
109+
{
110+
"properties",
111+
(o, n, t) => o.Properties = n.CreateMap(LoadOpenApiSchema, t)
112+
},
113+
{
114+
"additionalProperties", (o, n, _) =>
115+
{
116+
if (n is ValueNode)
117+
{
118+
o.AdditionalPropertiesAllowed = bool.Parse(n.GetScalarValue());
119+
}
120+
else
121+
{
122+
o.AdditionalProperties = LoadOpenApiSchema(n);
123+
}
124+
}
125+
},
126+
{
127+
"description",
128+
(o, n, _) => o.Description = n.GetScalarValue()
129+
},
130+
{
131+
"format",
132+
(o, n, _) => o.Format = n.GetScalarValue()
133+
},
134+
{
135+
"default",
136+
(o, n, _) => o.Default = n.CreateAny()
137+
},
138+
{
139+
"nullable",
140+
(o, n, _) => o.Nullable = bool.Parse(n.GetScalarValue())
141+
},
142+
{
143+
"discriminator",
144+
(o, n, _) => o.Discriminator = LoadDiscriminator(n)
145+
},
146+
{
147+
"readOnly",
148+
(o, n, _) => o.ReadOnly = bool.Parse(n.GetScalarValue())
149+
},
150+
{
151+
"writeOnly",
152+
(o, n, _) => o.WriteOnly = bool.Parse(n.GetScalarValue())
153+
},
154+
{
155+
"xml",
156+
(o, n, _) => o.Xml = LoadXml(n)
157+
},
158+
{
159+
"externalDocs",
160+
(o, n, _) => o.ExternalDocs = LoadExternalDocs(n)
161+
},
162+
{
163+
"example",
164+
(o, n, _) => o.Example = n.CreateAny()
165+
},
166+
{
167+
"deprecated",
168+
(o, n, _) => o.Deprecated = bool.Parse(n.GetScalarValue())
169+
},
170+
};
171+
172+
private static readonly PatternFieldMap<OpenApiSchema> _openApiSchemaPatternFields = new()
173+
{
174+
{s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))}
175+
};
176+
177+
public static OpenApiSchema LoadOpenApiSchema(ParseNode node, OpenApiDocument hostDocument = null)
178+
{
179+
var mapNode = node.CheckMapNode(OpenApiConstants.Schema);
180+
181+
var pointer = mapNode.GetReferencePointer();
182+
183+
if (pointer != null)
184+
{
185+
return new()
186+
{
187+
UnresolvedReference = true,
188+
Reference = node.Context.VersionService.ConvertToOpenApiReference(pointer, ReferenceType.Schema)
189+
};
190+
}
191+
192+
var schema = new OpenApiSchema();
193+
194+
foreach (var propertyNode in mapNode)
195+
{
196+
propertyNode.ParseField(schema, _openApiSchemaFixedFields, _openApiSchemaPatternFields);
197+
}
198+
199+
return schema;
200+
}
201+
}
202+
}

0 commit comments

Comments
 (0)