-
Notifications
You must be signed in to change notification settings - Fork 275
Expand file tree
/
Copy pathOpenApiResponseDeserializer.cs
More file actions
211 lines (184 loc) · 7.83 KB
/
OpenApiResponseDeserializer.cs
File metadata and controls
211 lines (184 loc) · 7.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
using System.Collections.Generic;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.Reader.ParseNodes;
namespace Microsoft.OpenApi.Reader.V2
{
/// <summary>
/// Class containing logic to deserialize Open API V2 document into
/// runtime Open API object model.
/// </summary>
internal static partial class OpenApiV2Deserializer
{
private static readonly FixedFieldMap<OpenApiResponse> _responseFixedFields = new()
{
{
"description",
(o, n, _) => o.Description = n.GetScalarValue()
},
{
"headers",
(o, n, t) => o.Headers = n.CreateMap(LoadHeader, t)
},
{
"examples", LoadExamples
},
{
"x-examples", LoadResponseExamplesExtension
},
{
"schema",
(o, n, t) => n.Context.SetTempStorage(TempStorageKeys.ResponseSchema, LoadSchema(n, t), o)
},
};
private static readonly PatternFieldMap<OpenApiResponse> _responsePatternFields =
new()
{
{s => s.StartsWith("x-") && !s.Equals(OpenApiConstants.ExamplesExtension, StringComparison.OrdinalIgnoreCase),
(o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))}
};
private static readonly AnyFieldMap<OpenApiMediaType> _mediaTypeAnyFields =
new()
{
{
OpenApiConstants.Example,
new(
m => m.Example,
(m, v) => m.Example = v,
m => m.Schema)
}
};
private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, ParsingContext context)
{
if (response.Content == null)
{
response.Content = new Dictionary<string, OpenApiMediaType>();
}
else if (context.GetFromTempStorage<bool>(TempStorageKeys.ResponseProducesSet, response))
{
// Process "produces" only once since once specified at operation level it cannot be overriden.
return;
}
var produces = context.GetFromTempStorage<List<string>>(TempStorageKeys.OperationProduces)
?? context.GetFromTempStorage<List<string>>(TempStorageKeys.GlobalProduces)
?? context.DefaultContentType ?? new List<string> { "application/octet-stream" };
var schema = context.GetFromTempStorage<OpenApiSchema>(TempStorageKeys.ResponseSchema, response);
var examples = context.GetFromTempStorage<Dictionary<string, IOpenApiExample>>(TempStorageKeys.Examples, response)
?? new Dictionary<string, IOpenApiExample>();
foreach (var produce in produces)
{
if (response.Content.TryGetValue(produce, out var produceValue))
{
if (schema != null)
{
produceValue.Schema = schema;
ProcessAnyFields(mapNode, produceValue, _mediaTypeAnyFields);
}
}
else
{
var mediaType = new OpenApiMediaType
{
Schema = schema,
Examples = examples
};
response.Content.Add(produce, mediaType);
}
}
context.SetTempStorage(TempStorageKeys.ResponseSchema, null, response);
context.SetTempStorage(TempStorageKeys.Examples, null, response);
context.SetTempStorage(TempStorageKeys.ResponseProducesSet, true, response);
}
private static void LoadResponseExamplesExtension(OpenApiResponse response, ParseNode node, OpenApiDocument hostDocument)
{
var examples = LoadExamplesExtension(node);
node.Context.SetTempStorage(TempStorageKeys.Examples, examples, response);
}
private static Dictionary<string, IOpenApiExample> LoadExamplesExtension(ParseNode node)
{
var mapNode = node.CheckMapNode(OpenApiConstants.ExamplesExtension);
var examples = new Dictionary<string, IOpenApiExample>();
foreach (var examplesNode in mapNode)
{
// Load the media type node as an OpenApiExample object
var example = new OpenApiExample();
var exampleNode = examplesNode.Value.CheckMapNode(examplesNode.Name);
foreach (var valueNode in exampleNode)
{
switch (valueNode.Name.ToLowerInvariant())
{
case "summary":
example.Summary = valueNode.Value.GetScalarValue();
break;
case "description":
example.Description = valueNode.Value.GetScalarValue();
break;
case "value":
example.Value = valueNode.Value.CreateAny();
break;
case "externalValue":
example.ExternalValue = valueNode.Value.GetScalarValue();
break;
}
}
examples.Add(examplesNode.Name, example);
}
return examples;
}
private static void LoadExamples(OpenApiResponse response, ParseNode node, OpenApiDocument hostDocument)
{
var mapNode = node.CheckMapNode("examples");
foreach (var mediaTypeNode in mapNode)
{
LoadExample(response, mediaTypeNode.Name, mediaTypeNode.Value);
}
}
private static void LoadExample(OpenApiResponse response, string mediaType, ParseNode node)
{
var exampleNode = node.CreateAny();
response.Content ??= new Dictionary<string, OpenApiMediaType>();
OpenApiMediaType mediaTypeObject;
if (response.Content.TryGetValue(mediaType, out var value))
{
mediaTypeObject = value;
}
else
{
mediaTypeObject = new()
{
Schema = node.Context.GetFromTempStorage<OpenApiSchema>(TempStorageKeys.ResponseSchema, response)
};
response.Content.Add(mediaType, mediaTypeObject);
}
mediaTypeObject.Example = exampleNode;
}
public static IOpenApiResponse LoadResponse(ParseNode node, OpenApiDocument hostDocument)
{
var mapNode = node.CheckMapNode("response");
var pointer = mapNode.GetReferencePointer();
if (pointer != null)
{
var reference = GetReferenceIdAndExternalResource(pointer);
return new OpenApiResponseReference(reference.Item1, hostDocument, reference.Item2);
}
var response = new OpenApiResponse();
foreach (var property in mapNode)
{
property.ParseField(response, _responseFixedFields, _responsePatternFields, hostDocument);
}
foreach (var mediaType in response.Content.Values)
{
if (mediaType.Schema != null)
{
ProcessAnyFields(mapNode, mediaType, _mediaTypeAnyFields);
}
}
return response;
}
}
}