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

Fix default values and matching schemas when oneOf / anyOf subschemas contain references #2272

Merged
merged 21 commits into from
Apr 13, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions packages/core/src/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,25 +263,17 @@ export default function validateFormData(
};
}

function isDict(v) {
return (
typeof v === "object" &&
v !== null &&
!(v instanceof Array) &&
!(v instanceof Date)
);
}

/**
* Get a similar schema where ref's are prefixed with "__rjsf_rootSchema"
NixBiks marked this conversation as resolved.
Show resolved Hide resolved
* This is used in isValid to make references to the rootSchema
*/
function withIdRefPrefix(schema) {
NixBiks marked this conversation as resolved.
Show resolved Hide resolved
const obj = { ...schema };
for (let key of Object.keys(obj)) {
const value = obj[key];
if (key === "$ref") {
obj[key] = "__rjsf_rootSchema" + value;
NixBiks marked this conversation as resolved.
Show resolved Hide resolved
} else if (isDict(value)) {
} else if (value.constructor === Object) {
obj[key] = withIdRefPrefix(value);
}
}
Expand All @@ -295,14 +287,28 @@ function withIdRefPrefix(schema) {
*/
export function isValid(schema, data, rootSchema) {
try {
// if rootSchema is given then we add that schema with an id.
// then we rewrite the schema ref's to point to the rootSchema using the id
// this accounts for the case where schema have references to models
// that lives in the rootSchema but not in the schema in question.
if (rootSchema) {
NixBiks marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think rootSchema is always given -- so maybe we can just remove this check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right - except for some tests, but I've just updated those tests to add the schema as rootSchema as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively I could leave the tests as is and have this instead

return ajv
  .addSchema(rootSchema || schema, ROOT_SCHEMA_PREFIX)
  .validate(withIdRefPrefix(schema), data);

So if no rootSchema is provided then the schema itself will be used. Any preferences with one or the other?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's better to just go ahead and update the tests rather than adding unnecessary functionality to this function.

return createAjvInstance()
const result = ajv
NixBiks marked this conversation as resolved.
Show resolved Hide resolved
.addSchema(rootSchema, "__rjsf_rootSchema")
.validate(withIdRefPrefix(schema), data);

// make sure we remove the rootSchema from the global ajv instance
ajv.removeSchema("__rjsf_rootSchema");
return result;
} else {
return ajv.validate(schema, data);
}
} catch (e) {
try {
// make sure we also remove the rootSchema if an error occured before removing but after adding
ajv.removeSchema("__rjsf_rootSchema");
} catch (e) {
return false;
}
return false;
}
NixBiks marked this conversation as resolved.
Show resolved Hide resolved
}