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

Draft 2020-12 #285

Merged
merged 2 commits into from
Jun 21, 2023
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ The goal of this library is to make JSON Schema generation done the way all popu
Inspired by Coursera Autoschema but uses `Scala Macros` instead of `Java Reflection`.

## Features
- Supports Json Schema `draft-04`, `draft-06`, `draft-07`, `draft-09`
- Supports Json Schema `draft-04`, `draft-06`, `draft-07`, `draft-09`, `draft-12`
- Supports `case classes`
- Supports `value classes`
- Supports `sealed trait enums`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.github.andyglow.jsonschema

import com.github.andyglow.json.Value._
import com.github.andyglow.jsonschema.JsonMatchers._
import json.Schema._
import json.schema.Version._
import org.scalatest.matchers.should.Matchers._
import org.scalatest.wordspec.AnyWordSpec

class AsDraft12Spec extends AnyWordSpec {

"AsValue.schema" should {

"emit const" in {

val a = `oneof`.of(
`const`("foo").withTitle("Foo").withDescription("f-o-o"),
`const`("bar").withTitle("Bar").withDescription("b-a-r")
)

val e = obj(
f"$$schema" -> "https://json-schema.org/draft/2020-12/schema",
f"$$id" -> "http://example.com/foobarbaz.json",
"oneOf" -> arr(
obj("const" -> "foo", "title" -> "Foo", "description" -> "f-o-o"),
obj("const" -> "bar", "title" -> "Bar", "description" -> "b-a-r")
)
)

AsValue.schema(
a,
Draft12(id = "http://example.com/foobarbaz.json")
) should beStructurallyEqualTo(e)
}

"emit Object" in {
import `object`.Field

val a = `object`(
Field("foo", `string`[String]),
Field("uuid", `string`(`string`.Format.`uuid`)),
Field("bar", `integer`, required = false),
Field("baz", `def`[Boolean]("my-bool", `boolean`))
)

val e = obj(
f"$$schema" -> "https://json-schema.org/draft/2020-12/schema",
f"$$id" -> "http://example.com/foobarbaz.json",
"type" -> "object",
"additionalProperties" -> false,
"required" -> arr("foo", "baz", "uuid"),
"properties" -> obj(
"foo" -> obj("type" -> "string"),
"uuid" -> obj("type" -> "string", "format" -> "uuid"),
"bar" -> obj("type" -> "integer"),
"baz" -> obj(f"$$ref" -> "#my-bool")
),
"$defs" -> obj("my-bool" -> obj(f"$$anchor" -> "my-bool", "type" -> "boolean"))
)

AsValue.schema(
a,
Draft12(id = "http://example.com/foobarbaz.json")
) should beStructurallyEqualTo(e)
}
}
}
30 changes: 30 additions & 0 deletions core/src/main/scala/com/github/andyglow/jsonschema/AsDraft12.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.github.andyglow.jsonschema

import com.github.andyglow.json.Value._
import json.Schema._
import json.schema.Version._

class AsDraft12(val v: Draft12) extends AsValue with AsDraftSupport with Post09 {

def schema(x: json.Schema[_]): obj = {
val base = obj(f"$$schema" -> v.uri, f"$$id" -> v.id)

val definitions = inferDefinitions(x)

base ++ {
if (definitions.fields.nonEmpty) obj("$defs" -> definitions) else obj()
} ++ apply(x)
}

override def buildRef(ref: String): String = s"#$ref"

override def inferDefinition(x: `def`[_], par: ParentSchema): (String, obj) = {
val ref = x.sig
ref -> (obj(f"$$anchor" -> ref) ++ apply(
x.tpe,
par orElse Some(x),
includeType = true,
isRoot = false
))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ trait AsDraftSupport {

private[jsonschema] def isDraft09 = this.isInstanceOf[AsDraft09]

private[jsonschema] def isDraft12 = this.isInstanceOf[AsDraft12]

type ParentSchema = Option[json.Schema[_]]

def apply(x: json.Schema[_]): obj = apply(x, None, includeType = true, isRoot = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ trait LowPriorityAsValueBuilder {
implicit val draft09: AsValueBuilder[Draft09] = new AsValueBuilder[Draft09] {
override def apply(v: Draft09): AsValue = new AsDraft09(v)
}

implicit val draft12: AsValueBuilder[Draft12] = new AsValueBuilder[Draft12] {
override def apply(v: Draft12): AsValue = new AsDraft12(v)
}
}

object AsValueBuilder extends LowPriorityAsValueBuilder
5 changes: 5 additions & 0 deletions core/src/main/scala/json/schema/Version.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@ object Version {

val uri: String = "https://json-schema.org/draft/2019-09/schema"
}

final case class Draft12(id: String) extends Version {

val uri: String = "https://json-schema.org/draft/2020-12/schema"
}
}