scala-jsonschema icon indicating copy to clipboard operation
scala-jsonschema copied to clipboard

Optional field should have additional `null` as type

Open endertunc opened this issue 5 years ago • 2 comments

First of all, thank you for such a great library and hard work!

I am having issue validation json with optional fields with null values. As mentioned in https://github.com/everit-org/json-schema/issues/16 optional values should have "type": "null" as valid value. However, this library does not add null as one of the possible values.

Note: I use circe for json + circe-schema(wrapper around everit) to validate schema

  import com.github.andyglow.jsonschema.AsCirce._
  import json.schema.Version._
  import io.circe.generic.auto._
  import io.circe.syntax._

  case class Example(a: String, b: Option[String])
  implicit val exampleSchema: Schema[Example] = json.Json.schema[Example]
  val validator                               = io.circe.schema.Schema.load(exampleSchema.asCirce(Draft07(id = "example")))

  println(Example("Hello", Some("World")).asJson.noSpaces)
  println(validator.validate(Example("Hello", Some("World")).asJson))
  println(Example("Hello", None).asJson.noSpaces)
  println(validator.validate(Example("Hello", None).asJson))

--------------------------------------------------------------------------------------------

  {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "example",
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "a": {
        "type": "string"
      },
      "b": {
        "type": "string"
      }
    },
    "required": [
      "a"
    ]
  }

  {"a":"Hello","b":"World"}
  Valid(())
  {"a":"Hello","b":null}
  Invalid(NonEmptyList(io.circe.schema.ValidationError$$anon$1: #/b: expected type: String, found: Null))

I did a quick look to source code but could not understand much. I feel like it might be an easy fix so please let me know if I can help somehow.

Thanks in advance!

endertunc avatar Jan 24 '20 10:01 endertunc

Hello, Ender! According to original comment Optionality concept is not equal to Nullability concept. And Json schema spec is pretty strict on this. And guys who maintain that library don't think it should be equal. Me neither. I mean spec says that optionality are regulated by required schema field. Right? Whereas if you need to support nulls - there is a workaround.

{
"properties": {
      "a": {
        "type": "string"
      },
      "b": {
         "anyOf": [
                { "type": "null"},
                {"type": "string"}
            ]
      }
    },
    "required": [
      "a", "b"
    ]
}

In this case b field is required and must be either a string or null. If we would remove b from required, we would see that b must be either a string or a null or a missed field. So what i am trying to say is there two are little different concepts, although often comes together.

By the way, I haven't checked how Cirke itself would handle the case you provided. Did you check?

But anyways, this is an interesting topic.

Can you tell me why do you need null support, btw?

andyglow avatar Feb 11 '20 00:02 andyglow

@andyglow thanks for your reply!

(with a little bit background) The reason why I need null support is that I would like to be able to tell the user what was wrong with the Json. Circe does not give you anything useful in that matter and I don't think I can blame them. I run schema validation as first step on my REST endpoints to be able to extract meaningful error messages. While I was writing test for my application. in one of my test, I got an error like Field someOptioanlField can not be null which seemed weird especially in Scala context. Then, I doubled check that Circe maps missing and null field to None for Optional fields as I would expect. That's when I decided to open this issue to discuss :)

I agree that Optionality and Nullability are two different concepts but as you already mentioned that they often comes together which is I believe why Circe decided to implemented the current behavior.

endertunc avatar Feb 11 '20 10:02 endertunc