eclipsesource/play-json-schema-validator

Return full list of validation errors

Closed this issue · 5 comments

Hi!

It's not a bug but i would like to have full stack of errors when validate json over schema. Play's json reads works like that, it tries to read every property in a object and then it result in a success object or array of failed properties. Currently your library returns first failed property, doesn't it?

Hi!
The validator should already report errors for all properties, e.g. when using the following schema

{
   "properties": {
     "title": { "type": "string", "minLength": 3 },
     "foo" :  { "type": "string", "pattern": "^[A-Z].*" }
   }
}

and passing {"title": "a", "foo": "a" } to the validate method it will report errors for title as well as foo:

[ {
  "schemaPath" : "#/properties/foo",
  "errors" : { },
  "msgs" : [ "a does not match pattern ^[A-Z].*" ],
  "value" : "a",
  "instancePath" : "/foo"
}, {
  "schemaPath" : "#/properties/title",
  "errors" : { },
  "msgs" : [ "a violates min length of 3" ],
  "value" : "a",
  "instancePath" : "/title"
} ]

Is this what you mean? If not, can you post an example and your expected outcome?
Thank you!

Yes, that's exactly what i mean

I've mistaken, it works:

scala> import com.eclipsesource.schema._
import com.eclipsesource.schema._

scala> import play.api.libs.json._
import play.api.libs.json._

scala> val schema = Json.fromJson[SchemaType](Json.obj("type" -> "object", "properties" -> Json.obj("name" -> Json.obj("type" -> "string"), "job" -> Json.obj("type" -> "string")), "required" -> List("name", "job")))
schema: play.api.libs.json.JsResult[com.eclipsesource.schema.SchemaType] = JsSuccess(object,)

scala> SchemaValidator.validate(schema.get, Json.obj().as[JsValue]).toString
res6: String = JsError(List((,List(ValidationError(List(Property job missing),WrappedArray({"schemaPath":"#","instancePath":"","value":{},"errors":{}})))), (,List(ValidationError(List(Property name missing),WrappedArray({"schemaPath":"#","instancePath":"","value":{},"errors":{}}))))))

There's is some bug in my code..
Thank you for reply!

Ah, no, i reproduced the problem:

scala> val result = SchemaValidator.validate(schema.get, Json.obj())
result: play.api.libs.json.JsResult[play.api.libs.json.JsObject] = JsError(List((,List(ValidationError(List(Property job missing),WrappedArray({"schemaPath":"#","instancePath":"","value":{},"errors":{}})))), (,List(ValidationError(List(Property name missing),WrappedArray({"schemaPath":"#","instancePath":"","value":{},"errors":{}}))))))

scala> result.asEither.left.map(err => JsError.toJson(err))
res3: Product with Serializable with scala.util.Either[play.api.libs.json.JsObject,play.api.libs.json.JsObject] = Left({"obj":[{"msg":["Property name missing"],"args":[{"schemaPath":"#","instancePath":"","value":{},"errors":{}}]}]})

It fails when i try to convert JsError to JsObject with JsError.toJson method. Where is "job" property?

JsError.toJson currently doesn't work with the result returned by the validator since it overwrites properties with the same name during the merge (in this case the returned array contains the empty instance path twice), therefore you have to use the toJson method on the returned result like mentioned here. Let me know if that works for you.
That said, the validator should probably merge entries within the returned result, such that it is compatible with JsError.

Yes, it works!
It seems like i used it before but forgot, too much information :)
Thank you!