Skip to content

Commit b4877f6

Browse files
Merge pull request #2280 from microsoft/mw/update-discriminator-mappings
feat: discriminator mappings now use schema references
1 parent 57cf7ed commit b4877f6

File tree

8 files changed

+50
-24
lines changed

8 files changed

+50
-24
lines changed

src/Microsoft.OpenApi/Models/OpenApiDiscriminator.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using Microsoft.OpenApi.Interfaces;
6+
using Microsoft.OpenApi.Models.References;
67
using Microsoft.OpenApi.Writers;
78

89
namespace Microsoft.OpenApi.Models
@@ -20,7 +21,7 @@ public class OpenApiDiscriminator : IOpenApiSerializable, IOpenApiExtensible
2021
/// <summary>
2122
/// An object to hold mappings between payload values and schema names or references.
2223
/// </summary>
23-
public IDictionary<string, string>? Mapping { get; set; } = new Dictionary<string, string>();
24+
public IDictionary<string, OpenApiSchemaReference>? Mapping { get; set; } = new Dictionary<string, OpenApiSchemaReference>();
2425

2526
/// <summary>
2627
/// This object MAY be extended with Specification Extensions.
@@ -38,7 +39,7 @@ public OpenApiDiscriminator() { }
3839
public OpenApiDiscriminator(OpenApiDiscriminator discriminator)
3940
{
4041
PropertyName = discriminator?.PropertyName ?? PropertyName;
41-
Mapping = discriminator?.Mapping != null ? new Dictionary<string, string>(discriminator.Mapping) : null;
42+
Mapping = discriminator?.Mapping != null ? new Dictionary<string, OpenApiSchemaReference>(discriminator.Mapping) : null;
4243
Extensions = discriminator?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(discriminator.Extensions) : null;
4344
}
4445

@@ -80,7 +81,13 @@ private void SerializeInternal(IOpenApiWriter writer)
8081
writer.WriteProperty(OpenApiConstants.PropertyName, PropertyName);
8182

8283
// mapping
83-
writer.WriteOptionalMap(OpenApiConstants.Mapping, Mapping, (w, s) => w.WriteValue(s));
84+
writer.WriteOptionalMap(OpenApiConstants.Mapping, Mapping, (w, s) =>
85+
{
86+
if (!string.IsNullOrEmpty(s.Reference.ReferenceV3) && s.Reference.ReferenceV3 is not null)
87+
{
88+
w.WriteValue(s.Reference.ReferenceV3);
89+
}
90+
});
8491
}
8592

8693
/// <summary>

src/Microsoft.OpenApi/Reader/V3/OpenApiDiscriminatorDeserializer.cs

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

4+
using System;
45
using System.Linq;
56
using Microsoft.OpenApi.Models;
7+
using Microsoft.OpenApi.Models.References;
68
using Microsoft.OpenApi.Reader.ParseNodes;
79

810
namespace Microsoft.OpenApi.Reader.V3
@@ -22,7 +24,7 @@ internal static partial class OpenApiV3Deserializer
2224
},
2325
{
2426
"mapping",
25-
(o, n, _) => o.Mapping = n.CreateSimpleMap(LoadString).Where(kv => kv.Value is not null).ToDictionary(kv => kv.Key, kv => kv.Value!)
27+
(o, n, doc) => o.Mapping = n.CreateSimpleMap((node) => LoadMapping(node, doc))
2628
}
2729
};
2830

@@ -40,5 +42,11 @@ public static OpenApiDiscriminator LoadDiscriminator(ParseNode node, OpenApiDocu
4042

4143
return discriminator;
4244
}
45+
public static OpenApiSchemaReference LoadMapping(ParseNode node, OpenApiDocument hostDocument)
46+
{
47+
var pointer = node.GetScalarValue() ?? throw new InvalidOperationException("Could not get a pointer reference");
48+
var reference = GetReferenceIdAndExternalResource(pointer);
49+
return new OpenApiSchemaReference(reference.Item1, hostDocument, reference.Item2);
50+
}
4351
}
4452
}

src/Microsoft.OpenApi/Reader/V3/OpenApiV3VersionService.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using Microsoft.OpenApi.Any;
8-
using Microsoft.OpenApi.Exceptions;
9-
using Microsoft.OpenApi.Extensions;
108
using Microsoft.OpenApi.Interfaces;
119
using Microsoft.OpenApi.Models;
12-
using Microsoft.OpenApi.Properties;
10+
using Microsoft.OpenApi.Models.References;
1311
using Microsoft.OpenApi.Reader.ParseNodes;
1412

1513
namespace Microsoft.OpenApi.Reader.V3
@@ -62,7 +60,8 @@ public OpenApiV3VersionService(OpenApiDiagnostic diagnostic)
6260
[typeof(OpenApiServer)] = OpenApiV3Deserializer.LoadServer,
6361
[typeof(OpenApiServerVariable)] = OpenApiV3Deserializer.LoadServerVariable,
6462
[typeof(OpenApiTag)] = OpenApiV3Deserializer.LoadTag,
65-
[typeof(OpenApiXml)] = OpenApiV3Deserializer.LoadXml
63+
[typeof(OpenApiXml)] = OpenApiV3Deserializer.LoadXml,
64+
[typeof(OpenApiSchemaReference)] = OpenApiV3Deserializer.LoadMapping
6665
};
6766

6867
public OpenApiDocument LoadDocument(RootNode rootNode)

src/Microsoft.OpenApi/Reader/V31/OpenApiDiscriminatorDeserializer.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using Microsoft.OpenApi.Extensions;
44
using Microsoft.OpenApi.Models;
5+
using Microsoft.OpenApi.Models.References;
56
using Microsoft.OpenApi.Reader.ParseNodes;
67

78
namespace Microsoft.OpenApi.Reader.V31
@@ -22,9 +23,9 @@ internal static partial class OpenApiV31Deserializer
2223
}
2324
},
2425
{
25-
"mapping", (o, n, _) =>
26+
"mapping", (o, n, doc) =>
2627
{
27-
o.Mapping = n.CreateSimpleMap(LoadString).Where(kv => kv.Value is not null).ToDictionary(kv => kv.Key, kv => kv.Value!);
28+
o.Mapping = n.CreateSimpleMap((node) => LoadMapping(node, doc));
2829
}
2930
}
3031
};
@@ -47,5 +48,12 @@ public static OpenApiDiscriminator LoadDiscriminator(ParseNode node, OpenApiDocu
4748

4849
return discriminator;
4950
}
51+
52+
public static OpenApiSchemaReference LoadMapping(ParseNode node, OpenApiDocument hostDocument)
53+
{
54+
var pointer = node.GetScalarValue() ?? throw new InvalidOperationException("Could not get a pointer reference");
55+
var reference = GetReferenceIdAndExternalResource(pointer);
56+
return new OpenApiSchemaReference(reference.Item1, hostDocument, reference.Item2);
57+
}
5058
}
5159
}

src/Microsoft.OpenApi/Reader/V31/OpenApiV31VersionService.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using Microsoft.OpenApi.Any;
8-
using Microsoft.OpenApi.Exceptions;
9-
using Microsoft.OpenApi.Extensions;
108
using Microsoft.OpenApi.Interfaces;
119
using Microsoft.OpenApi.Models;
12-
using Microsoft.OpenApi.Properties;
10+
using Microsoft.OpenApi.Models.References;
1311
using Microsoft.OpenApi.Reader.ParseNodes;
1412
using Microsoft.OpenApi.Reader.V3;
1513

@@ -61,7 +59,8 @@ public OpenApiV31VersionService(OpenApiDiagnostic diagnostic)
6159
[typeof(OpenApiServer)] = OpenApiV31Deserializer.LoadServer,
6260
[typeof(OpenApiServerVariable)] = OpenApiV31Deserializer.LoadServerVariable,
6361
[typeof(OpenApiTag)] = OpenApiV31Deserializer.LoadTag,
64-
[typeof(OpenApiXml)] = OpenApiV31Deserializer.LoadXml
62+
[typeof(OpenApiXml)] = OpenApiV31Deserializer.LoadXml,
63+
[typeof(OpenApiSchemaReference)] = OpenApiV31Deserializer.LoadMapping
6564
};
6665

6766
public OpenApiDocument LoadDocument(RootNode rootNode)

test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDiscriminatorTests.cs

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

4+
using System;
45
using System.IO;
56
using System.Threading.Tasks;
67
using Microsoft.OpenApi.Models;
8+
using Microsoft.OpenApi.Models.References;
79
using Microsoft.OpenApi.Reader;
810
using Xunit;
911

@@ -25,19 +27,21 @@ public async Task ParseBasicDiscriminatorShouldSucceed()
2527
memoryStream.Position = 0;
2628

2729
// Act
28-
var discriminator = OpenApiModelFactory.Load<OpenApiDiscriminator>(memoryStream, OpenApiSpecVersion.OpenApi3_0, OpenApiConstants.Yaml, new(), out var diagnostic, SettingsFixture.ReaderSettings);
30+
var openApiDocument = new OpenApiDocument();
31+
var discriminator = OpenApiModelFactory.Load<OpenApiDiscriminator>(memoryStream, OpenApiSpecVersion.OpenApi3_0, OpenApiConstants.Yaml, openApiDocument, out var diagnostic, SettingsFixture.ReaderSettings);
2932

3033
// Assert
3134
Assert.Equivalent(
32-
new OpenApiDiscriminator
33-
{
34-
PropertyName = "pet_type",
35-
Mapping =
35+
new OpenApiDiscriminator
36+
{
37+
PropertyName = "pet_type",
38+
Mapping =
3639
{
37-
["puppy"] = "#/components/schemas/Dog",
38-
["kitten"] = "Cat"
40+
["puppy"] = new OpenApiSchemaReference("Dog", openApiDocument),
41+
["kitten"] = new OpenApiSchemaReference("Cat" , openApiDocument, "https://gigantic-server.com/schemas/animals.json"),
42+
["monster"] = new OpenApiSchemaReference("schema.json" , openApiDocument, "https://gigantic-server.com/schemas/Monster/schema.json")
3943
}
40-
}, discriminator);
44+
}, discriminator);
4145
}
4246
}
4347
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
propertyName: pet_type
22
mapping:
33
puppy: '#/components/schemas/Dog'
4-
kitten: Cat
4+
kitten: https://gigantic-server.com/schemas/animals.json#/components/schemas/Cat
5+
monster: https://gigantic-server.com/schemas/Monster/schema.json

test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ namespace Microsoft.OpenApi.Models
699699
public OpenApiDiscriminator() { }
700700
public OpenApiDiscriminator(Microsoft.OpenApi.Models.OpenApiDiscriminator discriminator) { }
701701
public System.Collections.Generic.IDictionary<string, Microsoft.OpenApi.Interfaces.IOpenApiExtension>? Extensions { get; set; }
702-
public System.Collections.Generic.IDictionary<string, string>? Mapping { get; set; }
702+
public System.Collections.Generic.IDictionary<string, Microsoft.OpenApi.Models.References.OpenApiSchemaReference>? Mapping { get; set; }
703703
public string? PropertyName { get; set; }
704704
public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }
705705
public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { }

0 commit comments

Comments
 (0)