Skip to content

Commit 10c69a8

Browse files
committed
Create Json schema mappings with references in components
1 parent cf2106a commit 10c69a8

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

src/Microsoft.OpenApi.Readers/ParseNodes/MapNode.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Linq;
99
using System.Text.Json;
1010
using System.Text.Json.Nodes;
11+
using Json.Schema;
1112
using Microsoft.OpenApi.Any;
1213
using Microsoft.OpenApi.Interfaces;
1314
using Microsoft.OpenApi.Models;
@@ -123,6 +124,63 @@ public override Dictionary<string, T> CreateMapWithReference<T>(
123124
return nodes.Where(n => n != default).ToDictionary(k => k.key, v => v.value);
124125
}
125126

127+
public override Dictionary<string, JsonSchema> CreateJsonSchemaMapWithReference(
128+
ReferenceType referenceType,
129+
Func<MapNode, JsonSchema> map,
130+
OpenApiSpecVersion version)
131+
{
132+
var jsonMap = _node ?? throw new OpenApiReaderException($"Expected map while parsing {typeof(JsonSchema).Name}", Context);
133+
134+
var nodes = jsonMap.Select(
135+
n =>
136+
{
137+
var key = n.Key;
138+
(string key, JsonSchema value) entry;
139+
try
140+
{
141+
Context.StartObject(key);
142+
entry = (key,
143+
value: map(new MapNode(Context, (JsonObject)n.Value))
144+
);
145+
if (entry.value == null)
146+
{
147+
return default; // Body Parameters shouldn't be converted to Parameters
148+
}
149+
// If the component isn't a reference to another component, then point it to itself.
150+
if (entry.value.GetRef() == null)
151+
{
152+
var builder = new JsonSchemaBuilder();
153+
154+
// construct the Ref and append it to the builder
155+
var reference = version == OpenApiSpecVersion.OpenApi2_0 ? string.Concat("#/definitions/", entry.key) :
156+
string.Concat("#/components/schemas/", entry.key);
157+
158+
builder.Ref(reference);
159+
160+
// Append all the keywords in original schema to our new schema using a builder instance
161+
foreach (var keyword in entry.value.Keywords)
162+
{
163+
builder.Add(keyword);
164+
}
165+
entry.value = builder.Build();
166+
//entry.value.GetRef() = new OpenApiReference()
167+
//{
168+
// Type = referenceType,
169+
// Id = entry.key
170+
//};
171+
172+
}
173+
}
174+
finally
175+
{
176+
Context.EndObject();
177+
}
178+
return entry;
179+
}
180+
);
181+
return nodes.Where(n => n != default).ToDictionary(k => k.key, v => v.value);
182+
}
183+
126184
public override Dictionary<string, T> CreateSimpleMap<T>(Func<ValueNode, T> map)
127185
{
128186
var jsonMap = _node ?? throw new OpenApiReaderException($"Expected map while parsing {typeof(T).Name}", Context);

src/Microsoft.OpenApi.Readers/ParseNodes/ParseNode.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

44
using System;
55
using System.Collections.Generic;
66
using System.Text.Json.Nodes;
7+
using Json.Schema;
78
using Microsoft.OpenApi.Any;
89
using Microsoft.OpenApi.Interfaces;
910
using Microsoft.OpenApi.Models;
@@ -66,6 +67,14 @@ public virtual Dictionary<string, T> CreateMapWithReference<T>(
6667
throw new OpenApiReaderException("Cannot create map from this reference.", Context);
6768
}
6869

70+
public virtual Dictionary<string, JsonSchema> CreateJsonSchemaMapWithReference(
71+
ReferenceType referenceType,
72+
Func<MapNode, JsonSchema> map,
73+
OpenApiSpecVersion version)
74+
{
75+
throw new OpenApiReaderException("Cannot create map from this reference.", Context);
76+
}
77+
6978
public virtual List<T> CreateSimpleList<T>(Func<ValueNode, T> map)
7079
{
7180
throw new OpenApiReaderException("Cannot create simple list from this type of node.", Context);

src/Microsoft.OpenApi.Readers/V2/OpenApiDocumentDeserializer.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ internal static partial class OpenApiV2Deserializer
6464
o.Components = new();
6565
}
6666

67-
o.Components.Schemas = n.CreateMap(LoadSchema);
68-
}
67+
o.Components.Schemas = n.CreateJsonSchemaMapWithReference(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi2_0); }
6968
},
7069
{
7170
"parameters",

src/Microsoft.OpenApi.Readers/V3/OpenApiComponentsDeserializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ internal static partial class OpenApiV3Deserializer
2020
{
2121
private static readonly FixedFieldMap<OpenApiComponents> _componentsFixedFields = new()
2222
{
23-
{"schemas", (o, n) => o.Schemas = n.CreateMap(LoadSchema)},
23+
{"schemas", (o, n) => o.Schemas = n.CreateJsonSchemaMapWithReference(ReferenceType.Schema, LoadSchema, OpenApiSpecVersion.OpenApi3_0)},
2424
{"responses", (o, n) => o.Responses = n.CreateMapWithReference(ReferenceType.Response, LoadResponse)},
2525
{"parameters", (o, n) => o.Parameters = n.CreateMapWithReference(ReferenceType.Parameter, LoadParameter)},
2626
{"examples", (o, n) => o.Examples = n.CreateMapWithReference(ReferenceType.Example, LoadExample)},

0 commit comments

Comments
 (0)