gregsdennis/Manatee.Json

Not intuitive error message when value for property Format is not recognized

GregBalajewicz opened this issue · 10 comments

When a schema has an unexpected value for "format", it throw an unintuative error message. Perhaps a "unrecognized value of Int32 for format" would be better

TO REPRODUCE:

Schema:

{
  "id": "greg1",
  "$schema": "http://json-schema.org/draft-07/schema",
  "title": "test3 api schema",

  "type": "object",

  "properties": {
    "emplID": {
      "type": "integer",
      "format": "Int32",
      "description": "Employee's ID"
    }
  },
  "required": [ "emplID" ]
}

ERROR GENERATED :
NullReferenceException : Object reference not set to an instance of an object.
stack trace:
at Manatee.Json.Schema.FormatKeyword.Validate(SchemaValidationContext context)
at System.Linq.Enumerable.SelectIPartitionIterator2.ToList() at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
at Manatee.Json.Schema.JsonSchema.Validate(SchemaValidationContext context)
at Manatee.Json.Schema.PropertiesKeyword.Validate(SchemaValidationContext context)
at System.Linq.Enumerable.SelectIPartitionIterator2.ToList() at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
at Manatee.Json.Schema.JsonSchema.Validate(SchemaValidationContext context)
at Manatee.Json.Schema.JsonSchema.Validate(JsonValue json)
at Lcbo.Bimber.API.Utils.SchemaValidator2.Validate(String documentToValidate) in C:\Users\xtgab\Documents_projects\lcbo.bimber.api\Lcbo.Bimber.Api\Utils\SchemaValidator2.cs:line 76

This is a deserialization issue, not a validation issue, so validation error messages are moot here.

How are you deserializing the schema? There should be a check to validate the schema before deserializing it that doesn't seem to be happening.

Well, the json deserializes OK. it is a valid JSON. The issue is that validation does not recognize the value of the format field.

In fact, it seems to have problems with other format values. I ran into the same issue with:
"format": "date", in something like this :

"Status": {
      "type": "object",
      "properties": {
        "Original_Hire_Date": {
          "type": "string",
          "format": "date",
        },
        "Start_Date": {
          "type": "string",
          "format": "date",
        }
      },
      "required": [
        "Original_Hire_Date"
      ]
    },

Here is my code to deserialize the schema and do the validation:

                var serializer = new JsonSerializer();
                var json = JsonValue.Parse(schemaRaw);
                var mySchema = serializer.Deserialize<Manatee.Json.Schema.JsonSchema>(json);
                var val = JsonValue.Parse(documentToValidate);
                SchemaValidationResults results = mySchema.Validate(val);


Where are you getting schemaRaw?

The thing here is that the schema isn't being validated. If you're loading from a file, I suggest that you use JsonSchemaRegistry.Get() and pass in the file name as a URI. This way the schema is validated. You'll find that Int32 and date are not supported string format values (although date-time is supported). If it's hard-coded, I suggest that you build the schema in code rather than as a string.

You can add support for new string formats by using one of the StringFormat constructors. These will also register the new format for deserialization.

All that said, I did find a bug in that the system doesn't throw an exception when deserializing an unrecognized string format. I'll fix that.

I'm putting an isKnownFormat boolean in the AdditionalInfo dictionary on the result object. That should indicate to you whether the format was recognized.

https://www.nuget.org/packages/Manatee.Json/

Version 10.0.5 contains your fix.

Sorry @gregsdennis! I was not able to get to this.

I've consumed your update and it works as expected, thanks! However, personally, I think the failure should occur when the schema is read in, and an unrecognized format is encountered. Right now, the schema is parsed, but failure occurs at validation time - format not recognized. IMO, the failure should occur during schema load in time, but this is not a big deal.

And to answer your question, my schema is coming from an external file. I cannot build it in code

JSON Schema specifies

If the type of the instance to validate is not in this set, validation for this format attribute and instance SHOULD succeed.

These means that I shouldn't throw exceptions when I don't recognize a format. Technically, I need to revisit what I did for this change. Unrecognized formats should succeed by default, and this change makes them fail by default.

I'll add in an option to indicate whether they should succeed or fail, though.

Additionally, the spec also says

Implementations MAY support the "format" keyword as a validation assertion. Should they choose to do so:

  • they SHOULD implement validation for attributes defined below;
  • they SHOULD offer an option to disable validation for this keyword.

@GregBalajewicz with v10.1.0 I've added an option that will trigger an exception when deserializing a schema with an unknown format.