Expose Ajv in order to support alternate schemas#794
Expose Ajv in order to support alternate schemas#794johnrom wants to merge 5 commits intorjsf-team:masterfrom
Conversation
…tion, allowing users to validate jsonschema 4.0
|
Imo this code is clean and can be merged. |
|
Sorry for the delay in reviewing -- the holidays got the better of me. I agree that the use case is important and I agree equally that this approach probably isn't the way to go. Sharing a single global variable as the singleton validator is already probably not great, but if we start modifying it, I think it would be worse. I'm not a React expert either, but I think passing it as a prop, as you do in your final example, would be better. We could treat the existing |
|
Indeed, I also think that avoiding to have a global variable that anyone can change, it would probably be better to set the ajv variable from the props , something like : |
|
I think that the need to change validation schema is independent of the fact that the project uses a specific schema validator currently. I would prefer to use my final example above, but I would name the attribute |
- extranous properties in ui:order not throwing errors rjsf-team/react-jsonschema-form#814 - exported validator instance for customization rjsf-team/react-jsonschema-form#794
|
In which release will be included this feature ? |
|
Having another prop on https://github.com/epoberezkin/ajv#addschemaarrayobjectobject-schema--string-key---ajv As it stands I am likely going to have to downgrade the version of AlliterativelyThis could be bundled with providing an external validators - in which case providing an example validators using AJV would be ideal |
|
I do plan on finishing this pull request once I reach a point in a project where I need this functionality, probably in a week or two. However it seems we haven't come to an agreement on what method to use. Personally, I do not want to create a custom AJV instance especially because an update to this project may update AJV and my custom configuration might not even be valid / may create a conflict. Instead, I would like to provide a schema that this module would validate against, because even if down the line another JSON validator takes its place, this module will still understand that I want to use a specific schema to validate against. Per @narthollis note adding other customizable features, I think it'd be best to decide if those are implementation-independent and if we should support adding those customizable features as properties as well, leaving the current AJV implementation untouched -- as part of a different PR. |
|
My initial thought of passing a custom meta-schema is not going to work, because now additional work needs to be done in order to set up v4 meta-schema: I now think the three available options are:
|
|
The more I interact with and think about this issue, the more I am inclined to say that the property should be a custom validator, with defined shape eg interface CustomValidator {
validate(formData: any, schema: JSONSchema4 | JsonSchema6 | JsonSchema7): ValidationError[]
}
interface ValidationError {
name: string; // Ajv.ErrorObject.keyword
property: string; // Ajv.ErrorObject.dataPath
message: string; // Ajv.ErrorObject.message
params?: Ajv.ErrorParameters;
stack: string; // Ajv.ErrorObject.dataPath + Ajv.ErrorObject.message
}If React JSON Schema Form continues to use AJV then the internal AJV Error to Validation Error methods should be exposed to allow easier creation of a custom validator. My resonsing for using passing an Object with a validation method on it is to make it easier for sharing AJV instances (or instances of other validators) Usage could be something like: import metaSchema4 from 'ajv/lib/refs/json-schema-draft-04.json';
import { transformAjvErrors } from 'src/validate.js'; // this would need to be exported in some better way
class CustomValidator {
constructor() {
this.ajv = new Ajv({
meta: false,
extendRefs: true,
unknownFormats: 'ignore',
});
ajv.addMetaSchema(metaSchema4);
ajv._opts.defaultMeta = metaSchema.id;
}
public validate(formData: any, schema: JSONSchema4 | JsonSchema6 | JsonSchema7) {
this.ajv.validate(schema, formData);
return transformAjvErrors(this.ajv.errors);
}
}
export const MyCustomValidatorSingleton = new CustomValidator();
### Break
import * as React from 'react';
import RJSF from 'react-jsonschema-form';
import { MyCustomValidatorSingleton } from 'customValidator';
interface Props {
schema: JSONSchema4;
}
export default MyFormComponent extends React.PureComponent<Props> {
public render(): React.ReactNode {
return <RJSF
schema={this.props.schema}
customValidator={MyCustomValidatorSingleton}
/>;
}
} |
|
@narthollis that is certainly useful for the purpose you are describing. But I think in your case it might be easier to just allow the user to completely override the So the only change to your code would be the form call: I would say, however, that for someone who only wants to change the JSON Schema, this is overkill. I would rather something like adding callbacks to the AJV initialization process itself, allowing me to change the args used to create the object, and also allowing a dev to perform actions immediately after initialization. I'm going to do a proof of concept of that within this pull request as that is what I think my solution is. |
|
Unfortunately, I ended up removing the shared schema due to complexity so someone else will have to maintain a PR if there is interest in this. Edit: I'll leave this open while a path forward is determined. |
|
Unfortunately, I stopped using this repo almost a year ago, so I'm not the correct person to ask. I initially just wanted to use a v4 schema which hadn't been supported any longer, in order to integrate with another piece of technology from a backend server. I assumed that if I ran into that issue, that future schema versions would cause the issue again, so I recommended extensibility when implementing a fix. However I decided to manage the data models and presentation layer separately as things became more complex, so I won't be able to contribute any more thorough feedback to this PR. |
|
Okay, thanks for letting me know. Closing this as #1130 seems to do the job. |
Reasons for making this change
react-jsonschema-formdoes not expose its Ajv implementation so that users can configure Ajv with different schemas and whatnot. a la #783My use case: implementing ASP.Net React Forms via https://github.com/RSuter/NJsonSchema
This is probably not the way to do it, but I figured I'd offer my implementation. This implementation allows a dev to do this:
I might rather something like the following, but I'm also using TypeScript and it cried when I attempted to implement this so it tells me it might not be the way to go.
I might even go so far as to say the following is the real way, but I really have no idea which is the React way as I'm just learning it.
Either way, I'd like feedback before implementing anything further than I have.
Checklist
npm run cs-formaton my branch to conform my code to prettier coding style