diff --git a/schema-util/json/src/main/java/io/apicurio/registry/content/dereference/JsonSchemaDereferencer.java b/schema-util/json/src/main/java/io/apicurio/registry/content/dereference/JsonSchemaDereferencer.java index 8ce8bd6db4..e32cc25459 100644 --- a/schema-util/json/src/main/java/io/apicurio/registry/content/dereference/JsonSchemaDereferencer.java +++ b/schema-util/json/src/main/java/io/apicurio/registry/content/dereference/JsonSchemaDereferencer.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; @@ -132,6 +133,8 @@ public ContentHandle rewriteReferences(ContentHandle content, Map resolvedReferenceUrls) { if (node.isObject()) { rewriteInObject((ObjectNode) node, resolvedReferenceUrls); + } else if (node.isArray()) { + rewriteInArray((ArrayNode) node, resolvedReferenceUrls); } } @@ -155,7 +158,15 @@ private void rewriteInObject(ObjectNode node, Map resolvedRefere JsonNode fieldValue = node.get(fieldName); if (fieldValue.isObject()) { rewriteInObject((ObjectNode) fieldValue, resolvedReferenceUrls); + } else if (fieldValue.isArray()) { + rewriteInArray((ArrayNode) fieldValue, resolvedReferenceUrls); } } } + + private void rewriteInArray(ArrayNode node, Map resolvedReferenceUrls) { + node.forEach(innerNode -> { + rewriteIn(innerNode, resolvedReferenceUrls); + }); + } } diff --git a/schema-util/json/src/main/java/io/apicurio/registry/content/refs/JsonSchemaReferenceFinder.java b/schema-util/json/src/main/java/io/apicurio/registry/content/refs/JsonSchemaReferenceFinder.java index 356e645cab..0c6fa7187f 100644 --- a/schema-util/json/src/main/java/io/apicurio/registry/content/refs/JsonSchemaReferenceFinder.java +++ b/schema-util/json/src/main/java/io/apicurio/registry/content/refs/JsonSchemaReferenceFinder.java @@ -74,6 +74,10 @@ private static void findExternalTypesIn(JsonNode schema, Set externalTyp Entry field = fields.next(); findExternalTypesIn(field.getValue(), externalTypes); } + } else if (schema.isArray()) { + schema.forEach(innerNode -> { + findExternalTypesIn(innerNode, externalTypes); + }); } } diff --git a/schema-util/util-provider/src/test/java/io/apicurio/registry/content/dereference/JsonSchemaContentDereferencerTest.java b/schema-util/util-provider/src/test/java/io/apicurio/registry/content/dereference/JsonSchemaContentDereferencerTest.java index 627d725610..ab3d8bb6e6 100644 --- a/schema-util/util-provider/src/test/java/io/apicurio/registry/content/dereference/JsonSchemaContentDereferencerTest.java +++ b/schema-util/util-provider/src/test/java/io/apicurio/registry/content/dereference/JsonSchemaContentDereferencerTest.java @@ -98,4 +98,33 @@ public void testMultipleRefsUseSingleFile() { String expectedContent = resourceToString("expected-testDereference-property-level-json.json"); Assertions.assertEquals(normalizeMultiLineString(expectedContent), normalizeMultiLineString(modifiedContent.content())); } + + @Test + public void testDerefAllOf() throws Exception { + ContentHandle content = resourceToContentHandle("order.json"); + JsonSchemaDereferencer dereferencer = new JsonSchemaDereferencer(); + + Map resolvedReferences = new LinkedHashMap<>(); + + resolvedReferences.put("customer.json",resourceToContentHandle("customer.json")); + + ContentHandle modifiedContent = dereferencer.dereference(content, resolvedReferences); + + String expectedContent = resourceToString("expected-order-deref.json"); + Assertions.assertEquals(normalizeMultiLineString(expectedContent), + normalizeMultiLineString(modifiedContent.content())); + } + + @Test + public void testRewriteAllOfReferences() { + ContentHandle content = resourceToContentHandle("order.json"); + JsonSchemaDereferencer dereferencer = new JsonSchemaDereferencer(); + ContentHandle modifiedContent = dereferencer.rewriteReferences(content, + Map.of("customer.json", "https://www.example.org/schemas/customer.json")); + + ReferenceFinder finder = new JsonSchemaReferenceFinder(); + Set externalReferences = finder.findExternalReferences(modifiedContent); + Assertions.assertTrue(externalReferences + .contains(new JsonPointerExternalReference("https://www.example.org/schemas/customer.json"))); + } } diff --git a/schema-util/util-provider/src/test/resources/io/apicurio/registry/content/dereference/customer.json b/schema-util/util-provider/src/test/resources/io/apicurio/registry/content/dereference/customer.json new file mode 100644 index 0000000000..3369734393 --- /dev/null +++ b/schema-util/util-provider/src/test/resources/io/apicurio/registry/content/dereference/customer.json @@ -0,0 +1,22 @@ +{ + "$id": "https://test/schemas/CustomerSchema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Customer", + "type": "object", + "properties": { + "customerId": { + "type": "string", + "description": "A unique identifier for the customer." + }, + "name": { + "type": "string", + "description": "The full name of the customer." + }, + "email": { + "type": "string", + "format": "email", + "description": "The email address of the customer." + } + }, + "required": ["customerId", "name", "email"] +} \ No newline at end of file diff --git a/schema-util/util-provider/src/test/resources/io/apicurio/registry/content/dereference/expected-order-deref.json b/schema-util/util-provider/src/test/resources/io/apicurio/registry/content/dereference/expected-order-deref.json new file mode 100644 index 0000000000..4a986f4575 --- /dev/null +++ b/schema-util/util-provider/src/test/resources/io/apicurio/registry/content/dereference/expected-order-deref.json @@ -0,0 +1,83 @@ +{ + "allOf" : [ { + "title" : "Customer", + "type" : "object", + "properties" : { + "customerId" : { + "description" : "A unique identifier for the customer.", + "type" : "string" + }, + "name" : { + "description" : "The full name of the customer.", + "type" : "string" + }, + "email" : { + "format" : "email", + "description" : "The email address of the customer.", + "type" : "string" + } + }, + "required" : [ "customerId", "name", "email" ] + } ], + "oneOf" : [ { + "title" : "Customer", + "type" : "object", + "properties" : { + "customerId" : { + "description" : "A unique identifier for the customer.", + "type" : "string" + }, + "name" : { + "description" : "The full name of the customer.", + "type" : "string" + }, + "email" : { + "format" : "email", + "description" : "The email address of the customer.", + "type" : "string" + } + }, + "required" : [ "customerId", "name", "email" ] + } ], + "$schema" : "http://json-schema.org/draft-07/schema#", + "anyOf" : [ { + "title" : "Customer", + "type" : "object", + "properties" : { + "customerId" : { + "description" : "A unique identifier for the customer.", + "type" : "string" + }, + "name" : { + "description" : "The full name of the customer.", + "type" : "string" + }, + "email" : { + "format" : "email", + "description" : "The email address of the customer.", + "type" : "string" + } + }, + "required" : [ "customerId", "name", "email" ] + } ], + "title" : "Order", + "type" : "object", + "properties" : { + "orderId" : { + "description" : "A unique identifier for the order.", + "type" : "string" + }, + "orderDate" : { + "format" : "date-time", + "description" : "The date when the order was placed.", + "type" : "string" + }, + "orderTotal" : { + "format" : "float", + "description" : "The total amount of the order.", + "type" : "number" + } + }, + "required" : [ "orderId", "customer", "orderTotal" ], + "$id" : "https://test/schemas/OrderSchema.json" +} diff --git a/schema-util/util-provider/src/test/resources/io/apicurio/registry/content/dereference/order.json b/schema-util/util-provider/src/test/resources/io/apicurio/registry/content/dereference/order.json new file mode 100644 index 0000000000..145ee1207d --- /dev/null +++ b/schema-util/util-provider/src/test/resources/io/apicurio/registry/content/dereference/order.json @@ -0,0 +1,42 @@ +{ + "$id": "https://test/schemas/OrderSchema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Order", + "type": "object", + "allOf": [ + { + "$ref": "customer.json" + } + ], + "anyOf": [ + { + "$ref": "customer.json" + } + ], + "oneOf": [ + { + "$ref": "customer.json" + } + ], + "properties": { + "orderId": { + "type": "string", + "description": "A unique identifier for the order." + }, + "orderDate": { + "type": "string", + "format": "date-time", + "description": "The date when the order was placed." + }, + "orderTotal": { + "type": "number", + "format": "float", + "description": "The total amount of the order." + } + }, + "required": [ + "orderId", + "customer", + "orderTotal" + ] +} \ No newline at end of file