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

Custom formats for more data types #1039

Closed
m-mohr opened this issue Jul 8, 2019 · 6 comments
Closed

Custom formats for more data types #1039

m-mohr opened this issue Jul 8, 2019 · 6 comments

Comments

@m-mohr
Copy link

m-mohr commented Jul 8, 2019

What version of Ajv you are you using?

6.10.0

What problem do you want to solve?

Custom format-based validation for integers, objects, arrays.

What do you think is the correct solution to problem?

Currently, the documentation says addFormat only works for schemas that use the data types string and number. It would be helpful to also allow that for arrays, objects and integers. Maybe also schemas that don't have a data type set at all.

For example, I have a schema for EPSG codes:

{
	"type": "integer",
	"format": "epsg-code"
}

I'd like to use the format to check the integer data against a EPSG code database. I don't see a reason why the data types should be limited.

var ajvOptions = {
	format: 'full',
	formats: {
		'epsg-code': {type: 'integer', async: true, validate: this.validateEpsgCode.bind(this)}, // doesn' work
		'epsg-code-num': {type: 'number', async: true, validate: this.validateEpsgCodeNumeric.bind(this)} // works, but is counter-intuitive to tell users that they need to use number for integers when there's an integer data type in JSON schema
	}
};

I have use cases for arrays and objects, too.

Will you be able to implement it?

At least, I could make it work for me by changing the declaration of RULES in lib/compile/rules.js to

  var RULES = [
    { type: 'number',
      rules: [ { 'maximum': ['exclusiveMaximum'] },
               { 'minimum': ['exclusiveMinimum'] }, 'multipleOf', 'format' ] },
    { type: 'integer',
      rules: [ 'format' ] },
    { type: 'string',
      rules: [ 'maxLength', 'minLength', 'pattern', 'format' ] },
    { type: 'array',
      rules: [ 'maxItems', 'minItems', 'items', 'contains', 'uniqueItems', 'format' ] },
    { type: 'object',
      rules: [ 'maxProperties', 'minProperties', 'required', 'dependencies', 'propertyNames', 'format',
               { 'properties': ['additionalProperties', 'patternProperties' ] } ] },
    { rules: [ '$ref', 'const', 'enum', 'not', 'anyOf', 'oneOf', 'allOf', 'if', 'format' ] }
  ];

Unfortunately, I am not sure what side effects this may cause and whether it's the best way to do it.

Edit: After a discussion with some JSON Schema folks, it seems format is meant to be used also for non-string data types (see json-schema-org/json-schema-spec#759). So this issue seems valid, but they also pointed me towards custom keywords. Seems to be reasonable and I'll try them out, too.

@epoberezkin
Copy link
Member

JSON schema has no keywords that apply specifically for integers - they apply to all numbers. So formats follow this logic.

Docs do say though that you can define format for numbers, and "integer" is a subset of "number".

See the conversation here for the reason not to support other types than numbers and strings: #291 (comment)

@m-mohr
Copy link
Author

m-mohr commented Jul 24, 2019

Thanks for your answer, @epoberezkin. Unfortunately, I don't quite get your point.

For example, why can I use minimum with integer, but not format? Both are "inherited" from number.

I'd also find it useful for objects, for example. We have objects where depending on one property, the validation rules for the second property change. As this requires database lookups, I can't use oneOf/anyOf or so.

Issue for me is, that the schemas are not provided by me, so I can't introduce a custom keyword. Or can I add a custom keyword called format in ajv? ;-)

@epoberezkin
Copy link
Member

epoberezkin commented Aug 3, 2019

You can use format with integers, you just need to define it for “number” type. The point I made is about applicability - there are no keywords that apply only to integers, “minimum” you used as an example applies to all numbers, not only to integers.

@epoberezkin
Copy link
Member

You can try redefining some standard keywords, I believe it should work, but it is not recommended (and not tested).

@m-mohr
Copy link
Author

m-mohr commented Aug 3, 2019

@epoberezkin Thanks, but do I need to change the data type of the schema from integer to number? Or what do I need to define where? The callback doesn't get called for the example I specified initially. Or is that a bug?

@epoberezkin
Copy link
Member

It’s all documented - inside the format definition you need type: number, inside the schema itself - you can have type: integer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants