From 97219a67c0751fe41750babb7d4d18aa68fdcbe1 Mon Sep 17 00:00:00 2001 From: Jeff Lewis Date: Wed, 18 Oct 2023 14:29:16 -0600 Subject: [PATCH] JSON Schema Optional id Field --- .../src/internals/Extractors.scala | 13 ++++--- .../src/internals/JsonSchemaToIModel.scala | 5 ++- modules/json-schema/tests/src/RefSpec.scala | 34 +++++++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/modules/json-schema/src/internals/Extractors.scala b/modules/json-schema/src/internals/Extractors.scala index 29cf2d9..44a3c06 100644 --- a/modules/json-schema/src/internals/Extractors.scala +++ b/modules/json-schema/src/internals/Extractors.scala @@ -250,7 +250,7 @@ object Extractors { /* * The most complicated thing */ - abstract class JsonSchemaCaseRefBuilder(id: String, ns: Path) + abstract class JsonSchemaCaseRefBuilder(id: Option[String], ns: Path) extends smithytranslate.openapi.internals.CaseRefBuilder(ns) { def unapply(sch: Schema): Option[Either[ModelError, DefId]] = sch match { case ref: ReferenceSchema => @@ -260,11 +260,14 @@ object Extractors { // The number of `/` chars is not always consistent between the id and the refValue. val fileRegex = "^file:\\/*" val refValueNoPrefix = refValue.replaceFirst(fileRegex, "") - val idNoPrefix = id.replaceFirst(fileRegex, "") val sanitisedRefValue = - if (refValueNoPrefix.startsWith(idNoPrefix)) - refValueNoPrefix.drop(idNoPrefix.length()) - else refValue + id.map(_.replaceFirst(fileRegex, "")) + .collectFirst { + case idNoPrefix if (refValueNoPrefix.startsWith(idNoPrefix)) => + refValueNoPrefix.drop(idNoPrefix.length()) + } + .getOrElse(refValue) + Option(sanitisedRefValue).map(this.apply) case _ => None } diff --git a/modules/json-schema/src/internals/JsonSchemaToIModel.scala b/modules/json-schema/src/internals/JsonSchemaToIModel.scala index 5cb0875..42b4dff 100644 --- a/modules/json-schema/src/internals/JsonSchemaToIModel.scala +++ b/modules/json-schema/src/internals/JsonSchemaToIModel.scala @@ -69,7 +69,10 @@ private class JsonSchemaToIModel[F[_]: Parallel: TellShape: TellError]( implicit val F: Monad[F] = Parallel[F].monad private val CaseRef = - new Extractors.JsonSchemaCaseRefBuilder(jsonSchema.getId(), namespace) {} + new Extractors.JsonSchemaCaseRefBuilder( + Option(jsonSchema.getId()), + namespace + ) {} private val allSchemas: Vector[Local] = { val schemaNameSegment = diff --git a/modules/json-schema/tests/src/RefSpec.scala b/modules/json-schema/tests/src/RefSpec.scala index 01ecd55..e651404 100644 --- a/modules/json-schema/tests/src/RefSpec.scala +++ b/modules/json-schema/tests/src/RefSpec.scala @@ -254,4 +254,38 @@ final class RefSpec extends munit.FunSuite { TestUtils.runConversionTest(jsonSchString, expectedString) } + + test("schema with no id") { + val jsonSchString = """|{ + | "$schema": "http://json-schema.org/draft-07/schema#", + | "title": "Person", + | "type": "object", + | "properties": { + | "firstName": { + | "$ref": "#/$defs/name" + | }, + | "lastName": { + | "$ref": "#/$defs/name" + | } + | }, + | "$defs":{ + | "name": { + | "type": "string" + | } + | } + |} + |""".stripMargin + + val expectedString = """|namespace foo + | + |structure Person { + | firstName: Name, + | lastName: Name + |} + | + |string Name + |""".stripMargin + + TestUtils.runConversionTest(jsonSchString, expectedString) + } }