diff --git a/src/LEGO.AsyncAPI.Readers/V2/AsyncApiSchemaDeserializer.cs b/src/LEGO.AsyncAPI.Readers/V2/AsyncApiSchemaDeserializer.cs
index 582016eb..2131eb7e 100644
--- a/src/LEGO.AsyncAPI.Readers/V2/AsyncApiSchemaDeserializer.cs
+++ b/src/LEGO.AsyncAPI.Readers/V2/AsyncApiSchemaDeserializer.cs
@@ -130,7 +130,7 @@ public class JsonSchemaDeserializer
{
if (n is ValueNode && n.GetBooleanValueOrDefault(null) == false)
{
- a.AdditionalProperties = new NoAdditionalProperties();
+ a.AdditionalProperties = new FalseApiSchema();
}
else
{
@@ -139,7 +139,36 @@ public class JsonSchemaDeserializer
}
},
{
- "items", (a, n) => { a.Items = LoadSchema(n); }
+ "items", (a, n) =>
+ {
+ if (n is ValueNode && n.GetBooleanValueOrDefault(null) == false)
+ {
+ a.Items = new FalseApiSchema();
+ }
+ else
+ {
+ a.Items = LoadSchema(n);
+ }
+ }
+ },
+ {
+ "additionalItems", (a, n) =>
+ {
+ if (n is ValueNode && n.GetBooleanValueOrDefault(null) == false)
+ {
+ a.AdditionalItems = new FalseApiSchema();
+ }
+ else
+ {
+ a.AdditionalItems = LoadSchema(n);
+ }
+ }
+ },
+ {
+ "patternProperties", (a, n) => { a.PatternProperties = n.CreateMap(LoadSchema); }
+ },
+ {
+ "propertyNames", (a, n) => { a.PropertyNames = LoadSchema(n); }
},
{
"contains", (a, n) => { a.Contains = LoadSchema(n); }
diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiConstants.cs b/src/LEGO.AsyncAPI/Models/AsyncApiConstants.cs
index 2d3ae13c..37b1b45d 100644
--- a/src/LEGO.AsyncAPI/Models/AsyncApiConstants.cs
+++ b/src/LEGO.AsyncAPI/Models/AsyncApiConstants.cs
@@ -138,5 +138,8 @@ public static class AsyncApiConstants
public const string MaxMessageBytes = "max.message.bytes";
public const string TopicConfiguration = "topicConfiguration";
public const string GeoReplication = "geo-replication";
+ public const string AdditionalItems = "additionalItems";
+ public const string PropertyNames = "propertyNames";
+ public const string PatternProperties = "patternProperties";
}
}
diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiSchema.cs b/src/LEGO.AsyncAPI/Models/AsyncApiSchema.cs
index 1de5542b..85fcc13c 100644
--- a/src/LEGO.AsyncAPI/Models/AsyncApiSchema.cs
+++ b/src/LEGO.AsyncAPI/Models/AsyncApiSchema.cs
@@ -159,6 +159,13 @@ public class AsyncApiSchema : IAsyncApiReferenceable, IAsyncApiExtensible, IAsyn
///
public AsyncApiSchema Items { get; set; }
+ ///
+ /// follow JSON Schema definition: https://json-schema.org/draft-07/json-schema-release-notes.html
+ /// Value MUST be an object and not an array. Inline or referenced schema MUST be of a Schema Object
+ /// and not a standard JSON Schema. items MUST be present if the type is array.
+ ///
+ public AsyncApiSchema AdditionalItems { get; set; }
+
///
/// follow JSON Schema definition: https://json-schema.org/draft-07/json-schema-release-notes.html.
///
@@ -197,6 +204,8 @@ public class AsyncApiSchema : IAsyncApiReferenceable, IAsyncApiExtensible, IAsyn
///
public AsyncApiSchema AdditionalProperties { get; set; }
+ public IDictionary PatternProperties { get; set; } = new Dictionary();
+
///
/// follow JSON Schema definition: https://json-schema.org/draft-07/json-schema-release-notes.html.
///
@@ -335,7 +344,24 @@ public void SerializeV2WithoutReference(IAsyncApiWriter writer)
writer.WriteOptionalCollection(AsyncApiConstants.Required, this.Required, (w, s) => w.WriteValue(s));
// items
- writer.WriteOptionalObject(AsyncApiConstants.Items, this.Items, (w, s) => s.SerializeV2(w));
+ if (this.Items is FalseApiSchema)
+ {
+ writer.WriteOptionalProperty(AsyncApiConstants.Items, false);
+ }
+ else
+ {
+ writer.WriteOptionalObject(AsyncApiConstants.Items, this.Items, (w, s) => s.SerializeV2(w));
+ }
+
+ // additionalItems
+ if (this.AdditionalItems is FalseApiSchema)
+ {
+ writer.WriteOptionalProperty(AsyncApiConstants.AdditionalItems, false);
+ }
+ else
+ {
+ writer.WriteOptionalObject(AsyncApiConstants.AdditionalItems, this.AdditionalItems, (w, s) => s.SerializeV2(w));
+ }
// maxItems
writer.WriteOptionalProperty(AsyncApiConstants.MaxItems, this.MaxItems);
@@ -356,7 +382,7 @@ public void SerializeV2WithoutReference(IAsyncApiWriter writer)
writer.WriteOptionalProperty(AsyncApiConstants.MinProperties, this.MinProperties);
// additionalProperties
- if (this.AdditionalProperties is NoAdditionalProperties)
+ if (this.AdditionalProperties is FalseApiSchema)
{
writer.WriteOptionalProperty(AsyncApiConstants.AdditionalProperties, false);
}
@@ -365,6 +391,10 @@ public void SerializeV2WithoutReference(IAsyncApiWriter writer)
writer.WriteOptionalObject(AsyncApiConstants.AdditionalProperties, this.AdditionalProperties, (w, s) => s.SerializeV2(w));
}
+ writer.WriteOptionalMap(AsyncApiConstants.PatternProperties, this.PatternProperties, (w, s) => s.SerializeV2(w));
+
+ writer.WriteOptionalObject(AsyncApiConstants.PropertyNames, this.PropertyNames, (w, s) => s.SerializeV2(w));
+
// discriminator
writer.WriteOptionalProperty(AsyncApiConstants.Discriminator, this.Discriminator);
diff --git a/src/LEGO.AsyncAPI/Models/JsonSchema/FalseApiSchema.cs b/src/LEGO.AsyncAPI/Models/JsonSchema/FalseApiSchema.cs
new file mode 100644
index 00000000..40746fb3
--- /dev/null
+++ b/src/LEGO.AsyncAPI/Models/JsonSchema/FalseApiSchema.cs
@@ -0,0 +1,10 @@
+namespace LEGO.AsyncAPI.Models
+{
+ ///
+ /// An object representing 'false' for properties of AsyncApiSchema that can be false OR a schema.
+ ///
+ ///
+ public class FalseApiSchema : AsyncApiSchema
+ {
+ }
+}
diff --git a/src/LEGO.AsyncAPI/Models/JsonSchema/NoAdditionalProperties.cs b/src/LEGO.AsyncAPI/Models/JsonSchema/NoAdditionalProperties.cs
deleted file mode 100644
index 700d3351..00000000
--- a/src/LEGO.AsyncAPI/Models/JsonSchema/NoAdditionalProperties.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) The LEGO Group. All rights reserved.
-
-namespace LEGO.AsyncAPI.Models
-{
- ///
- /// An object representing 'false' for the 'additionalProperties' property of AsyncApiSchema.
- ///
- ///
- public class NoAdditionalProperties : AsyncApiSchema
- {
- }
-}
diff --git a/test/LEGO.AsyncAPI.Tests/Models/AsyncApiSchema_Should.cs b/test/LEGO.AsyncAPI.Tests/Models/AsyncApiSchema_Should.cs
index 4b99a465..31647d3e 100644
--- a/test/LEGO.AsyncAPI.Tests/Models/AsyncApiSchema_Should.cs
+++ b/test/LEGO.AsyncAPI.Tests/Models/AsyncApiSchema_Should.cs
@@ -71,7 +71,9 @@ public class AsyncApiSchema_Should
MaxLength = 15,
},
},
- AdditionalProperties = new NoAdditionalProperties(),
+ AdditionalProperties = new FalseApiSchema(),
+ Items = new FalseApiSchema(),
+ AdditionalItems = new FalseApiSchema(),
},
["property4"] = new AsyncApiSchema
{
@@ -93,6 +95,26 @@ public class AsyncApiSchema_Should
MinLength = 2,
},
},
+ PatternProperties = new Dictionary()
+ {
+ {
+ "^S_",
+ new AsyncApiSchema()
+ {
+ Type = SchemaType.String,
+ }
+ },
+ {
+ "^I_", new AsyncApiSchema()
+ {
+ Type = SchemaType.Integer,
+ }
+ },
+ },
+ PropertyNames = new AsyncApiSchema()
+ {
+ Pattern = "^[A-Za-z_][A-Za-z0-9_]*$",
+ },
AdditionalProperties = new AsyncApiSchema
{
Properties = new Dictionary
@@ -103,8 +125,28 @@ public class AsyncApiSchema_Should
},
},
},
+ Items = new AsyncApiSchema
+ {
+ Properties = new Dictionary
+ {
+ ["Property9"] = new AsyncApiSchema
+ {
+ Type = SchemaType.String | SchemaType.Null,
+ },
+ },
+ },
+ AdditionalItems = new AsyncApiSchema
+ {
+ Properties = new Dictionary
+ {
+ ["Property10"] = new AsyncApiSchema
+ {
+ Type = SchemaType.String | SchemaType.Null,
+ },
+ },
+ },
},
- ["property9"] = new AsyncApiSchema
+ ["property11"] = new AsyncApiSchema
{
Const = new AsyncApiString("aSpecialConstant"),
},
@@ -387,6 +429,8 @@ public void SerializeAsJson_WithAdvancedSchemaObject_V2Works()
""title"": ""title1"",
""properties"": {
""property1"": {
+ ""items"": false,
+ ""additionalItems"": false,
""properties"": {
""property2"": {
""type"": ""integer""
@@ -399,6 +443,26 @@ public void SerializeAsJson_WithAdvancedSchemaObject_V2Works()
""additionalProperties"": false
},
""property4"": {
+ ""items"": {
+ ""properties"": {
+ ""Property9"": {
+ ""type"": [
+ ""null"",
+ ""string""
+ ]
+ }
+ }
+ },
+ ""additionalItems"": {
+ ""properties"": {
+ ""Property10"": {
+ ""type"": [
+ ""null"",
+ ""string""
+ ]
+ }
+ }
+ },
""properties"": {
""property5"": {
""properties"": {
@@ -421,9 +485,20 @@ public void SerializeAsJson_WithAdvancedSchemaObject_V2Works()
]
}
}
+ },
+ ""patternProperties"": {
+ ""^S_"": {
+ ""type"": ""string""
+ },
+ ""^I_"": {
+ ""type"": ""integer""
+ }
+ },
+ ""propertyNames"": {
+ ""pattern"": ""^[A-Za-z_][A-Za-z0-9_]*$""
}
},
- ""property9"": {
+ ""property11"": {
""const"": ""aSpecialConstant""
}
},
@@ -443,13 +518,15 @@ public void SerializeAsJson_WithAdvancedSchemaObject_V2Works()
}
[Test]
- public void Deserialize_WithAdditionalProperties_Works()
+ public void Deserialize_WithAdvancedSchema_Works()
{
// Arrange
var json = @"{
""title"": ""title1"",
""properties"": {
""property1"": {
+ ""items"": false,
+ ""additionalItems"": false,
""properties"": {
""property2"": {
""type"": ""integer""
@@ -462,6 +539,26 @@ public void Deserialize_WithAdditionalProperties_Works()
""additionalProperties"": false
},
""property4"": {
+ ""items"": {
+ ""properties"": {
+ ""Property9"": {
+ ""type"": [
+ ""null"",
+ ""string""
+ ]
+ }
+ }
+ },
+ ""additionalItems"": {
+ ""properties"": {
+ ""Property10"": {
+ ""type"": [
+ ""null"",
+ ""string""
+ ]
+ }
+ }
+ },
""properties"": {
""property5"": {
""properties"": {
@@ -484,9 +581,20 @@ public void Deserialize_WithAdditionalProperties_Works()
]
}
}
+ },
+ ""patternProperties"": {
+ ""^S_"": {
+ ""type"": ""string""
+ },
+ ""^I_"": {
+ ""type"": ""integer""
+ }
+ },
+ ""propertyNames"": {
+ ""pattern"": ""^[A-Za-z_][A-Za-z0-9_]*$""
}
},
- ""property9"": {
+ ""property11"": {
""const"": ""aSpecialConstant""
}
},