Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenAPI: support sibling values for reference schemas #1020

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ trait EndpointsWithCustomErrors
recSchema <- captureReferencedSchemasRec(schema)
} yield recSchema

allReferencedSchemas.filter(_.name.contains("Book"))
allReferencedSchemas.collect {
case ref: Schema.Reference if ref.original.isDefined =>
ref.name -> ref.original.get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ trait JsonSchemas extends algebra.JsonSchemas with TuplesSchemas {
val docs: DocumentedJsonSchema
)

class RecordReference[A](
val name: String,
referencedRecord: Record[A]
) extends Record[A](referencedRecord.ujsonSchema, referencedRecord.docs.withName(name)) {
Comment on lines +47 to +50
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting - I was expecting to see a subclass like this on DocumentedRecord, not Record.

Should it ever be possible to have a RecordReference inside of a RecordReference? Eg. RecordReference("foo", RecordReference("bar", RecordReference("baz", ...)))? I see some effort here to avoid that case, but I can't tell yet if that is an invariant.

def withName(name: String) = new RecordReference(name, referencedRecord)

def withExample(example: => ujson.Value): RecordReference[A] =
new RecordReference(
name,
new Record(referencedRecord.ujsonSchema, referencedRecord.docs.withExample(example))
)
}

class Record[A](
override val ujsonSchema: ujsonSchemas.Record[A],
override val docs: DocumentedRecord
Expand Down Expand Up @@ -399,7 +412,8 @@ trait JsonSchemas extends algebra.JsonSchemas with TuplesSchemas {
}

def namedRecord[A](schema: Record[A], name: String): Record[A] =
new Record(schema.ujsonSchema, schema.docs.withName(name))
new RecordReference(name, schema)
//new Record(schema.ujsonSchema, schema.docs.withName(name))

def namedTagged[A](schema: Tagged[A], name: String): Tagged[A] =
new Tagged(schema.ujsonSchema, schema.docs.withName(name))
Expand Down Expand Up @@ -539,10 +553,16 @@ trait JsonSchemas extends algebra.JsonSchemas with TuplesSchemas {
case s: LazySchema => LazySchema(s.name, updatedDocs(s.value))
case s: OneOf => s.copy(example = Some(exampleJson))
}
new JsonSchema(
schema.ujsonSchema,
updatedDocs(schema.docs)
)
schema match {
case s: RecordReference[A] =>
println(s"RECORDREFERENCE ${s.name}")
s.withName(s.name + "$").withExample(exampleJson)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a clever idea, but I'm not sure it'll actually work unless the name mangling is made more complicated.

Consider the case where the same JsonSchema is re-used twice to create two other schemas that just each have their examples changed. Since both calls for adding the example will use withExampleJsonSchema, they'll both end up adding the same $ to the initial schema's name. We're now back where we started with a a collision in the schema name.

case _ =>
new JsonSchema(
schema.ujsonSchema,
updatedDocs(schema.docs)
)
}
}

def withTitleRecord[A](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,25 @@ object OpenApi {
* See <https://stackoverflow.com/a/41752575/3072788>.
*/
val refSchemaName = ujson.Str(Schema.Reference.toRefPath(reference.name))

/*
* Set sibling schema fields
*/
for (
description <- reference.description orElse reference.original.flatMap(_.description)
) {
fields += "description" -> ujson.Str(description)
}
for (example <- reference.example orElse reference.original.flatMap(_.example)) {
fields += "example" -> example
}
for (title <- reference.title orElse reference.original.flatMap(_.title)) {
fields += "title" -> title
}
for (default <- reference.default orElse reference.original.flatMap(_.default)) {
fields += "default" -> default
}

if (fields.isEmpty) {
fields += "$ref" -> refSchemaName
} else {
Expand Down
Loading