diff --git a/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/OpenAPISchema.java b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/OpenAPISchema.java
index 19c57b67..313094b0 100644
--- a/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/OpenAPISchema.java
+++ b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/OpenAPISchema.java
@@ -2,12 +2,13 @@
import com.asyncapi.v3.jackson.schema.openapi.OpenAPISchemaAdditionalPropertiesDeserializer;
import com.asyncapi.v3.jackson.schema.openapi.OpenAPISchemaAnyValueDeserializer;
+import com.asyncapi.v3.schema.openapi.properties.Discriminator;
+import com.asyncapi.v3.schema.openapi.properties.Extensions;
+import com.asyncapi.v3.schema.openapi.properties.ExternalDocumentation;
+import com.asyncapi.v3.schema.openapi.properties.XML;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
+import lombok.*;
import org.jetbrains.annotations.Nullable;
import java.math.BigDecimal;
@@ -34,7 +35,8 @@
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class OpenAPISchema {
+@EqualsAndHashCode(callSuper = true)
+public class OpenAPISchema extends Extensions {
/**
* Schema name.
diff --git a/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/Discriminator.java b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/Discriminator.java
similarity index 97%
rename from asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/Discriminator.java
rename to asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/Discriminator.java
index 5ebb1431..ca5ab32c 100644
--- a/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/Discriminator.java
+++ b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/Discriminator.java
@@ -1,4 +1,4 @@
-package com.asyncapi.v3.schema.openapi;
+package com.asyncapi.v3.schema.openapi.properties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
diff --git a/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/Extensions.java b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/Extensions.java
new file mode 100644
index 00000000..042bd076
--- /dev/null
+++ b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/Extensions.java
@@ -0,0 +1,46 @@
+package com.asyncapi.v3.schema.openapi.properties;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * @see Specification Extensions
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@JsonIgnoreProperties({"extensions"})
+public class Extensions {
+
+ private static final Pattern extensionPropertyNamePattern = Pattern.compile("^x-.*");
+
+ /**
+ * Extension fields in the form x-extension-field-name for the exposed API.
+ */
+ @Nullable
+ @JsonAnyGetter
+ protected Map extensions;
+
+ @JsonAnySetter
+ protected final void readExtensionProperty(String name, Object value) {
+ if (extensionPropertyNamePattern.matcher(name).matches()) {
+ if (extensions == null) {
+ extensions = new HashMap<>();
+ }
+
+ extensions.put(name, value);
+ } else {
+ throw new IllegalArgumentException(String.format("\"%s\" is not valid extension property", name));
+ }
+ }
+
+}
diff --git a/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/ExternalDocumentation.java b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/ExternalDocumentation.java
similarity index 87%
rename from asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/ExternalDocumentation.java
rename to asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/ExternalDocumentation.java
index 1f58895b..e3cb9e9d 100644
--- a/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/ExternalDocumentation.java
+++ b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/ExternalDocumentation.java
@@ -1,11 +1,8 @@
-package com.asyncapi.v3.schema.openapi;
+package com.asyncapi.v3.schema.openapi.properties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
+import lombok.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -22,7 +19,8 @@
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class ExternalDocumentation {
+@EqualsAndHashCode(callSuper = true)
+public class ExternalDocumentation extends Extensions {
/**
* A short description of the target documentation.
diff --git a/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/XML.java b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/XML.java
similarity index 94%
rename from asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/XML.java
rename to asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/XML.java
index 3cb9d85f..cfd5a0de 100644
--- a/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/XML.java
+++ b/asyncapi-core/src/main/java/com/asyncapi/v3/schema/openapi/properties/XML.java
@@ -1,11 +1,8 @@
-package com.asyncapi.v3.schema.openapi;
+package com.asyncapi.v3.schema.openapi.properties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
+import lombok.*;
import org.jetbrains.annotations.Nullable;
/**
@@ -21,7 +18,8 @@
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class XML {
+@EqualsAndHashCode(callSuper = true)
+public class XML extends Extensions {
/**
* Replaces the name of the element/attribute used for the described schema property.
diff --git a/asyncapi-core/src/test/kotlin/com/asyncapi/v3/schema/openapi/OpenAPISchemaTest.kt b/asyncapi-core/src/test/kotlin/com/asyncapi/v3/schema/openapi/OpenAPISchemaTest.kt
index 618fe5ad..13ccc763 100644
--- a/asyncapi-core/src/test/kotlin/com/asyncapi/v3/schema/openapi/OpenAPISchemaTest.kt
+++ b/asyncapi-core/src/test/kotlin/com/asyncapi/v3/schema/openapi/OpenAPISchemaTest.kt
@@ -2,8 +2,7 @@ package com.asyncapi.v3.schema.openapi
import com.asyncapi.v3.ClasspathUtils
import com.asyncapi.v3.schema.SchemaProvider
-import com.asyncapi.v3.schema.openapi.properties.ExampleEnumDefaultArrayTest
-import com.asyncapi.v3.schema.openapi.properties.ExampleEnumDefaultNullTest
+import com.asyncapi.v3.schema.openapi.properties.*
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.ObjectMapper
import org.junit.jupiter.api.Assertions
@@ -79,10 +78,13 @@ class OpenAPISchemaTest {
class XMLs: ArgumentsProvider {
override fun provideArguments(context: ExtensionContext?): Stream {
+ val extendedXML = XML(
+ "animal", "http://example.com/schema/sample", "sample", true, true
+ )
+ extendedXML.extensions = mapOf(Pair("x-extension-property", "value"))
+
return Stream.of(
- Arguments.of("/json/v3/schema/openapi/xml.json", XML(
- "animal", "http://example.com/schema/sample", "sample", true, true
- )),
+ Arguments.of("/json/v3/schema/openapi/xml.json", extendedXML),
Arguments.of("/json/v3/schema/openapi/xml-attribute.json", XML.builder().attribute(true).build()),
Arguments.of("/json/v3/schema/openapi/xml-name-replacement.json", XML.builder().name("animal").build()),
Arguments.of("/json/v3/schema/openapi/xml-prefix-and-namespace.json", XML.builder()
@@ -115,10 +117,11 @@ class OpenAPISchemaTest {
class ExternalDocumentations: ArgumentsProvider {
override fun provideArguments(context: ExtensionContext?): Stream {
+ val extendedExternalDocumentation = ExternalDocumentation("Find more info here", "https://example.com")
+ extendedExternalDocumentation.extensions = mapOf(Pair("x-extension-property", "value"))
+
return Stream.of(
- Arguments.of("/json/v3/schema/openapi/externaldocumentation.json", ExternalDocumentation(
- "Find more info here", "https://example.com"
- )),
+ Arguments.of("/json/v3/schema/openapi/externaldocumentation.json", extendedExternalDocumentation),
Arguments.of("/json/v3/schema/openapi/externaldocumentation-url.json", ExternalDocumentation(
null, "https://example.com"
)),
diff --git a/asyncapi-core/src/test/kotlin/com/asyncapi/v3/schema/openapi/SchemaTest.kt b/asyncapi-core/src/test/kotlin/com/asyncapi/v3/schema/openapi/SchemaTest.kt
index e75fa004..c0c9f91f 100644
--- a/asyncapi-core/src/test/kotlin/com/asyncapi/v3/schema/openapi/SchemaTest.kt
+++ b/asyncapi-core/src/test/kotlin/com/asyncapi/v3/schema/openapi/SchemaTest.kt
@@ -1,12 +1,15 @@
package com.asyncapi.v3.schema.openapi
import com.asyncapi.v3.schema.SchemaProvider
+import com.asyncapi.v3.schema.openapi.properties.Discriminator
+import com.asyncapi.v3.schema.openapi.properties.ExternalDocumentation
+import com.asyncapi.v3.schema.openapi.properties.XML
import java.math.BigDecimal
class SchemaTest: SchemaProvider {
override fun openAPISchema(): OpenAPISchema {
- return OpenAPISchema.builder()
+ val schema = OpenAPISchema.builder()
.name("schema name")
.title("schema title")
.multipleOf(BigDecimal(2.5))
@@ -163,6 +166,9 @@ class SchemaTest: SchemaProvider {
)
))
.build()
+ schema.extensions = mapOf(Pair("x-extension-property", "value"))
+
+ return schema
}
}
\ No newline at end of file
diff --git a/asyncapi-core/src/test/resources/json/v3/schema/openapi/externaldocumentation.json b/asyncapi-core/src/test/resources/json/v3/schema/openapi/externaldocumentation.json
index 19ba32ce..20aa0964 100644
--- a/asyncapi-core/src/test/resources/json/v3/schema/openapi/externaldocumentation.json
+++ b/asyncapi-core/src/test/resources/json/v3/schema/openapi/externaldocumentation.json
@@ -1,4 +1,5 @@
{
"description": "Find more info here",
- "url": "https://example.com"
+ "url": "https://example.com",
+ "x-extension-property": "value"
}
\ No newline at end of file
diff --git a/asyncapi-core/src/test/resources/json/v3/schema/openapi/schema.json b/asyncapi-core/src/test/resources/json/v3/schema/openapi/schema.json
index f5f9add9..0c529e6b 100644
--- a/asyncapi-core/src/test/resources/json/v3/schema/openapi/schema.json
+++ b/asyncapi-core/src/test/resources/json/v3/schema/openapi/schema.json
@@ -170,5 +170,6 @@
"dog": "#/components/schemas/Dog",
"monster": "https://gigantic-server.com/schemas/Monster/schema.json"
}
- }
+ },
+ "x-extension-property": "value"
}
\ No newline at end of file
diff --git a/asyncapi-core/src/test/resources/json/v3/schema/openapi/xml.json b/asyncapi-core/src/test/resources/json/v3/schema/openapi/xml.json
index d8eaf4dc..dfe05fba 100644
--- a/asyncapi-core/src/test/resources/json/v3/schema/openapi/xml.json
+++ b/asyncapi-core/src/test/resources/json/v3/schema/openapi/xml.json
@@ -3,5 +3,6 @@
"namespace": "http://example.com/schema/sample",
"prefix": "sample",
"attribute": true,
- "wrapped": true
+ "wrapped": true,
+ "x-extension-property": "value"
}
\ No newline at end of file