-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Add more schemas to validate against #1130
Conversation
Such a schema fails to be validated: {
"$ref": "#/definitions/Dataset",
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"Dataset": {
"properties": {
"datasetId": {
"description": "A user-specified unique ID for this BigQuery dataset.",
"maxLength": 1024,
"minLength": 1,
"pattern": "^[_a-zA-Z0-9]+$",
"title": "Dataset ID",
"type": "string"
},
"defaultTableExpirationMs": {
"description": "yadayada",
"title": "Default table expiration",
"type": "string"
},
"description": {
"description": "A user-friendly description of the BigQuery dataset.",
"title": "Description",
"type": "string"
},
"friendlyName": {
"description": "A descriptive name for the BigQuery dataset.",
"title": "Friendly name",
"type": "string"
},
"labels": {
"additionalProperties": { "type": "string" },
"description": "To organize your project, add arbitrary labels as key/value pairs to the BigQuery dataset. Use labels to indicate different environments, services, teams, and so on.",
"title": "Labels",
"type": "object",
"x-googleProperty": { "type": "LABELS" }
},
"location": {
"default": "US",
"description": "The geographic location where the BigQuery dataset should reside.",
"enum": ["US", "EU"],
"title": "Location",
"type": "string"
}
},
"required": ["datasetId"],
"type": "object"
}
},
"form": [
{
"key": "datasetId",
"validationMessage": "Must contain only letters, numbers, or underscores. Max length 1024."
},
"location",
"friendlyName",
"description",
"labels"
]
} And there are no errors in console and they do not get displayed, as written |
src/validate.js
Outdated
}); | ||
//add more schemas to validate against, draft-7 remains default | ||
ajv.addMetaSchema(require("ajv/lib/refs/json-schema-draft-04.json")); | ||
ajv.addMetaSchema(require("ajv/lib/refs/json-schema-draft-06.json")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a fan of these lines, this means that we always load in JS 4,6 and 7 definition, but we only need one normally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then maybe hide them under some kind of flag? Something like
<Form enableDraft4 ... />
and in validate.js
:
if(enableDraft4){
ajv.addMetaSchema(require("ajv/lib/refs/json-schema-draft-04.json"));
}
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aerfio Perhaps is there some way to call addMetaSchema
based on the value for $schema
in the schema definition itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when this is compiled by webpack, even if they are if
statements, all the JSON files will be in the bundled file.
I think we should rather have a way of doing :
<Form
jsonSchema={require("ajv/lib/refs/json-schema-draft-04.json"}
</Form>
@epicfaace Did you mean something like this? Regexp matches both "http://json-schema.org/draft-04/schema#" and "http://json-schema.org/draft-04/schema" and draft-06 respectively, (look at "#" sign at the end), because both of those two addresses work. @edi9999 what do you think about this? |
@aerfio , I think @edi9999 's proposal is that we do not include draft-04 or draft-06 within react-jsonschema-form, as it would unnecessarily increase our bundle size. Rather, if someone wants to use draft-04, they must install
Did that make sense? Would you be able to change your PR to work this way instead? |
@epicfaace @edi9999 ok, I think now we have the least invasive change, I just added I'll wait with documentation/tests till I hear what do you think about this :P |
Looks good to me !! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good -- is there a reason why it's called additionalSchema
instead of jsonSchema
? Will passing a value for additionalSchema
make ajv validate both for the latest draft and for the schema you passed in?
src/components/Form.js
Outdated
@@ -58,9 +58,10 @@ export default class Form extends Component { | |||
const { definitions } = schema; | |||
const formData = getDefaultFormState(schema, props.formData, definitions); | |||
const retrievedSchema = retrieveSchema(schema, definitions, formData); | |||
|
|||
const additionalSchema = | |||
props.additionalSchema || this.props.additionalSchema; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between props.additionalSchema
and this.props.additionalSchema
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unnecesary fallback, good catch!
src/validate.js
Outdated
}); | ||
//flag indicating whether we've already added custom schemas | ||
let addedAdditionalSchemas = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would we be disallowed from adding schemas multiple times ?
I could see a case where you would have schema-06 for one form, and schema-04 for an other form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@glasserc You can't add the same schema multiple times, ajv throws errors:
If you want to you can add multiple schemas at once, like so additionalSchema ={[ schema1, schema2 ]}
And if you want to validate one form using draft-6 and one using draft-4 you'd just use correct $schema
in your schema, like in example provided in my second comment, read this for clarification https://github.com/epoberezkin/ajv#validateschemaobject-schema---boolean .
If schema has $schema property, then the schema with this id (that should be previously added) is used to validate passed schema.
also
By default this method is called automatically when the schema is added, so you rarely need to use it directly.
@epicfaace They're additional jsonSchemas :P variable name can be changed, no problem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok makes sense !
@epicfaace According to http://json-schema.org/latest/json-schema-core.html#rfc.section.6.4
|
a82988b
to
f8f65ec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, I suggested a few changes to wording.
In addition to those changes, can you do the following:
- update the propTypes on the
<Form>
component - add some tests for passing in different schemas to metaSchema
- add a console error - if someone has entered a value
$schema
but hasn't added the proper metaSchema (see my comment on validate.js)
src/validate.js
Outdated
ajv.addMetaSchema(metaSchema); | ||
addedMetaSchemas = true; | ||
} | ||
|
||
try { | ||
ajv.validate(schema, formData); | ||
} catch (e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a console.error
here so if the schema is invalid, the user gets an error?
I'll probably write those tests tomorrow, don't merge for now! :D |
639043d
to
b438f4d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few more changes.
Additionally, @aerfio , I'm wondering about the metaSchema
prop -- is there really a need to be able to pass in multiple values for a metaSchema
? A schema will only have a single value for the $schema
attribute, anyway. Unless you can think of a use case for having multiple values in metaSchema
, I think we should just accept a single value for it. (It's also unintuitive for a singular property -- metaSchema
-- to accept an array)
(Let me loop you in @edi9999 since you first suggested being able to have multiple metaSchema
's)
On one hand I agree with you @epicfaace, but on the other it would be taking out features, that ajv already supports. It would be useful in a case when we don't really know which draft will finally use, (like getting data from some kind of backend) so we can preemptively add e.g. draft-4 and draft-6. And prop name |
@epicfaace What do you think? |
Yeah, I see your logic here. If I set (In fact, if that's the case, it may even be clearer to rename |
a4f7b7c
to
c3b539b
Compare
src/validate.js
Outdated
// swallow errors thrown in ajv due to invalid schemas, these | ||
// still get displayed | ||
} catch (err) { | ||
console.error(err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, my bad -- I didn't realize that as per the comment, even if the errors aren't logged to the console, they still get displayed. I think you can safely remove the console.error and revert back to the original strategy of not doing anything in the catch block.
ok @epicfaace, I've changed the prop name and updated docs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes! Few more things.
src/validate.js
Outdated
// swallow errors thrown in ajv due to invalid schemas, these | ||
// still get displayed | ||
} catch (err) { | ||
console.error(err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, my bad -- I didn't realize that as per the comment, even if the errors aren't logged to the console, they still get displayed. I think you can safely remove the console.error and revert back to the original strategy of not doing anything in the catch block.
docs/validation.md
Outdated
|
||
render(( | ||
<Form schema={schema} | ||
additionalMetaSchemas={additionalMetaSchemas}/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make additionalMetaSchemas
always an array, just for consistency?
d60e300
to
2ec6ecc
Compare
@epicfaace OK, I have deleted Only thing that may matter is that error produced by validation errors doesn't have all the fields that normal error have, it only has Unless we always guarantee that errors have specific fields, but I couldn't find anything about it in docs |
@aerfio I think that what you did works well and makes sense -- nice work! One thing to keep in mind is that ajv actually throws an error when the $schema given is invalid (rather than adding it to the |
src/validate.js
Outdated
// swallow errors thrown in ajv due to invalid schemas, these | ||
// still get displayed | ||
} catch (err) { | ||
validationErrors = err; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aerfio validationErrors
is an object, not an array, right? Would it make more sense to rename it to validationError
?
if (Array.isArray(parent.__errors)) { | ||
// We store the list of errors for this node in a property named __errors | ||
// to avoid name collision with a possible sub schema field named | ||
// "errors" (see `validate.createErrorHandler`). | ||
parent.__errors = parent.__errors.concat(message); | ||
} else { | ||
parent.__errors = [message]; | ||
if (message) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aerfio when would message
be undefined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@epicfaace Error thrown by ajv has only name and stack fields, name is Error
, stack is like in pic above
Advantage of using message field is that while form has validation errors, then all fields are red, opposite to #1130 (comment)
6bbd64b
to
7469b1a
Compare
@epicfaace The case you are refering to, when ajv throws errors connected to bad schema are already handled, it's even tested behaviour https://github.com/mozilla-services/react-jsonschema-form/pull/1130/files#diff-6654a6c320ad438fbbb53fa54fe3b95dR307 And regarding docs - could you please add it in that PR, if you're already writing it? Choose what version you like, with |
Will do. One more thing -- since we're adding meta schema errors (i.e., "no schema with key or ref "http://json-schema.org/draft-04/schema#\"") to the |
@epicfaace We are already doing it, because we're merging But those specific errors do not have |
@aerfio I think it would be better if errorSchema has every error that is in errors. Maybe one way to do it is like this:
The errorSchema constructed looks like this (and then the error does not show up twice):
So if we have a problem with the wrong $schema, can we construct an error list like this?
|
@epicfaace I have reduced validation errors to only those with error message starting with And I have added
to errorSchema. |
@aerfio everything looks good, thanks! |
@epicfaace thanks! when can we expect next release? 😀 |
* Add more schemas to validate against * Edit validate.js so that it calls addMetaSchema conditionally * Add props which accepts custom schemas for ajv * remove unnecesary fallback * rename variable name * add documentation for `metaSchema` prop * Update docs/validation.md Co-Authored-By: aerfio <[email protected]> * Update src/validate.js Co-Authored-By: aerfio <[email protected]> * Update src/validate.js Co-Authored-By: aerfio <[email protected]> * Update docs/validation.md Co-Authored-By: aerfio <[email protected]> * Update docs/validation.md Co-Authored-By: aerfio <[email protected]> * Update docs/validation.md Co-Authored-By: aerfio <[email protected]> * return errors from validation in validateFormData * add initial tests for meta schemas * add one proper test case * add more test cases * Update docs/validation.md Co-Authored-By: aerfio <[email protected]> * Add test cases for multiple metaSchemas in validateFormData * Change prop name and update docs * Change additionalMetaSchemas prop to array only and remove console.error * make sure that validateFormData's additionalMetaShemas argument is always an array * Commit "broken" test to see whether they pass * Fix tests and create new Ajv instance when additionalMetaSchemas changes * fix: create new ajv instance when additionalMetaSchemas prop is null, add tests * handle validation errors * fix tests and delete validation errors * Delete unneeded field in return statement * dont stop showing red overlay when validation errors are present * Make errors and test more sensible * rename variable * handle only $schema related errors * fix tests
Reasons for making this change
Right now we have no clear way to validate data using anything other then draft-6, which is default for ajv version 5. By updating ajv to newest available version (6.7.0) and making changes listed here: https://github.com/epoberezkin/ajv#using-version-6 we would be able to validate data using other drafts. There are no breaking changes between v5 and v6: https://github.com/epoberezkin/ajv/releases/tag/v6.0.0
Checklist
npm run cs-format
on my branch to conform my code to prettier coding style