diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs
index c629f78be..8877faac8 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs
@@ -50,6 +50,11 @@ public static class OpenApiConstants
///
public const string Title = "title";
+ ///
+ /// Field: Const
+ ///
+ public const string Const = "const";
+
///
/// Field: Type
///
diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs
index c2456286c..0215ac522 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs
@@ -83,6 +83,11 @@ public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiRe
///
public virtual JsonSchemaType? Type { get; set; }
+ ///
+ /// Follow JSON Schema definition: https://json-schema.org/draft/2020-12/json-schema-validation
+ ///
+ public virtual string Const { get; set; }
+
///
/// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00
/// While relying on JSON Schema's defined formats,
@@ -347,6 +352,7 @@ public OpenApiSchema(OpenApiSchema schema)
{
Title = schema?.Title ?? Title;
Id = schema?.Id ?? Id;
+ Const = schema?.Const ?? Const;
Schema = schema?.Schema ?? Schema;
Comment = schema?.Comment ?? Comment;
Vocabulary = schema?.Vocabulary != null ? new Dictionary(schema.Vocabulary) : null;
@@ -563,6 +569,7 @@ internal void WriteV31Properties(IOpenApiWriter writer)
writer.WriteProperty(OpenApiConstants.Id, Id);
writer.WriteProperty(OpenApiConstants.DollarSchema, Schema);
writer.WriteProperty(OpenApiConstants.Comment, Comment);
+ writer.WriteProperty(OpenApiConstants.Const, Const);
writer.WriteOptionalMap(OpenApiConstants.Vocabulary, Vocabulary, (w, s) => w.WriteValue(s));
writer.WriteOptionalMap(OpenApiConstants.Defs, Definitions, (w, s) => s.SerializeAsV31(w));
writer.WriteProperty(OpenApiConstants.DynamicRef, DynamicRef);
diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs
index a7b55e109..011e0b930 100644
--- a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs
+++ b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs
@@ -17,6 +17,9 @@ public class OpenApiSchemaReference : OpenApiSchema
internal OpenApiSchema _target;
private readonly OpenApiReference _reference;
private string _description;
+ private JsonNode _default;
+ private JsonNode _example;
+ private IList _examples;
private OpenApiSchema Target
{
@@ -90,6 +93,8 @@ internal OpenApiSchemaReference(OpenApiSchema target, string referenceId)
///
public override JsonSchemaType? Type { get => Target.Type; set => Target.Type = value; }
///
+ public override string Const { get => Target.Const; set => Target.Const = value; }
+ ///
public override string Format { get => Target.Format; set => Target.Format = value; }
///
public override string Description
@@ -114,7 +119,11 @@ public override string Description
///
public override decimal? MultipleOf { get => Target.MultipleOf; set => Target.MultipleOf = value; }
///
- public override JsonNode Default { get => Target.Default; set => Target.Default = value; }
+ public override JsonNode Default
+ {
+ get => _default ??= Target.Default;
+ set => _default = value;
+ }
///
public override bool ReadOnly { get => Target.ReadOnly; set => Target.ReadOnly = value; }
///
@@ -152,9 +161,17 @@ public override string Description
///
public override OpenApiDiscriminator Discriminator { get => Target.Discriminator; set => Target.Discriminator = value; }
///
- public override JsonNode Example { get => Target.Example; set => Target.Example = value; }
+ public override JsonNode Example
+ {
+ get => _example ??= Target.Example;
+ set => _example = value;
+ }
///
- public override IList Examples { get => Target.Examples; set => Target.Examples = value; }
+ public override IList Examples
+ {
+ get => _examples ??= Target.Examples;
+ set => Target.Examples = value;
+ }
///
public override IList Enum { get => Target.Enum; set => Target.Enum = value; }
///
diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs
index 5dc76b7fb..9c035da0d 100644
--- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs
+++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs
@@ -131,6 +131,10 @@ internal static partial class OpenApiV31Deserializer
}
}
},
+ {
+ "const",
+ (o, n, _) => o.Const = n.GetScalarValue()
+ },
{
"allOf",
(o, n, t) => o.AllOf = n.CreateList(LoadSchema, t)
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs
index 967bb0f3e..5f149b021 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs
@@ -452,5 +452,48 @@ public void SerializeSchemaWithJsonSchemaKeywordsWorks()
schema.Vocabulary.Keys.Count.Should().Be(5);
schemaString.MakeLineBreaksEnvironmentNeutral().Should().Be(expected.MakeLineBreaksEnvironmentNeutral());
}
+
+ [Fact]
+ public void ParseSchemaWithConstWorks()
+ {
+ var expected = @"{
+ ""$schema"": ""https://json-schema.org/draft/2020-12/schema"",
+ ""required"": [
+ ""status""
+ ],
+ ""type"": ""object"",
+ ""properties"": {
+ ""status"": {
+ ""const"": ""active"",
+ ""type"": ""string""
+ },
+ ""user"": {
+ ""required"": [
+ ""role""
+ ],
+ ""type"": ""object"",
+ ""properties"": {
+ ""role"": {
+ ""const"": ""admin"",
+ ""type"": ""string""
+ }
+ }
+ }
+ }
+}";
+
+ var path = Path.Combine(SampleFolderPath, "schemaWithConst.json");
+
+ // Act
+ var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_1, out _);
+ schema.Properties["status"].Const.Should().Be("active");
+ schema.Properties["user"].Properties["role"].Const.Should().Be("admin");
+
+ // serialization
+ var writer = new StringWriter();
+ schema.SerializeAsV31(new OpenApiJsonWriter(writer));
+ var schemaString = writer.ToString();
+ schemaString.MakeLineBreaksEnvironmentNeutral().Should().Be(expected.MakeLineBreaksEnvironmentNeutral());
+ }
}
}
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithConst.json b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithConst.json
new file mode 100644
index 000000000..ec0a0c794
--- /dev/null
+++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithConst.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "const": "active"
+ },
+ "user": {
+ "type": "object",
+ "properties": {
+ "role": {
+ "type": "string",
+ "const": "admin"
+ }
+ },
+ "required": [ "role" ]
+ }
+ },
+ "required": [ "status" ]
+}
diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
index 3fe034011..8f9f8ed41 100644
--- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
+++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt
@@ -398,6 +398,7 @@ namespace Microsoft.OpenApi.Models
public const string Comment = "$comment";
public const string Components = "components";
public const string ComponentsSegment = "/components/";
+ public const string Const = "const";
public const string Consumes = "consumes";
public const string Contact = "contact";
public const string Content = "content";
@@ -882,6 +883,7 @@ namespace Microsoft.OpenApi.Models
public virtual System.Collections.Generic.IList AllOf { get; set; }
public virtual System.Collections.Generic.IList AnyOf { get; set; }
public virtual string Comment { get; set; }
+ public virtual string Const { get; set; }
public virtual System.Text.Json.Nodes.JsonNode Default { get; set; }
public virtual System.Collections.Generic.IDictionary Definitions { get; set; }
public virtual bool Deprecated { get; set; }
@@ -1222,6 +1224,7 @@ namespace Microsoft.OpenApi.Models.References
public override System.Collections.Generic.IList AllOf { get; set; }
public override System.Collections.Generic.IList AnyOf { get; set; }
public override string Comment { get; set; }
+ public override string Const { get; set; }
public override System.Text.Json.Nodes.JsonNode Default { get; set; }
public override System.Collections.Generic.IDictionary Definitions { get; set; }
public override bool Deprecated { get; set; }