JSON 架构提取所需字段
JSON Schema extract the required fields
我需要从 JSON-Schema+Data 中获取必填字段的列表。
目前,我们正在使用 AJV 通过 JSON 架构在我们的表单中获取错误消息,并且效果很好。
我需要一种方法来获取所有必填字段(即使已填写),以便将那些带有 * 的字段标记为 "required"。必填字段可能会根据架构和数据组合而变化。
也曾尝试破解 tv4 来提取所需的字段,但没有成功。
请帮忙。
此类模式的示例:
{
"type": "object",
"required": [
"checkbox"
],
"properties": {
"checkbox": {
"type": "boolean"
},
"textbox": {
"type": "string"
}
},
"oneOf": [
{
"required": [
"textbox"
],
"properties": {
"checkbox": {
"enum": [
true
]
}
}
},
{
"properties": {
"checkbox": {
"enum": [
false
]
}
}
}
],
"additionalProperties": false
}
此函数以递归方式抓取模式索引,因此也许您可以稍微调整一下
// https://github.com/pubkey/rxdb/blob/master/src/rx-schema.js
export function getIndexes(jsonID, prePath = '') {
let indexes = [];
Object.entries(jsonID).forEach(entry => {
const key = entry[0];
const obj = entry[1];
const path = key === 'properties' ? prePath : util.trimDots(prePath + '.' + key);
if (obj.index)
indexes.push([path]);
if (typeof obj === 'object' && !Array.isArray(obj)) {
const add = getIndexes(obj, path);
indexes = indexes.concat(add);
}
});
if (prePath === '') {
const addCompound = jsonID.compoundIndexes || [];
indexes = indexes.concat(addCompound);
}
indexes = indexes
.filter((elem, pos, arr) => arr.indexOf(elem) === pos); // unique;
return indexes;
}
重读您的问题最简单的方法是
- 在页面加载时获取 Json 数据,
- 迭代 json 数据以删除有效值(参见 示例 1),
- 调用tv4.validateMultiple(数据、模式),
- 检查结果对象并获取必填字段(参见示例 2)。
样本 1
for(let prop in data) {
if(data.hasOwnProperty(prop) {
//set value to null, -1, or some other universally bad value
data[prop]...value = null;
}
}
样本 2
let result = tv4.validateMultiple(data, schema);
let required = result.errors;
我们解决了这个问题:
分叉 tv4(tv4 - 因为它很容易编辑):
https://github.com/mikila85/tv4
正在输出一个 "Requireds".
的数组
我们迭代了每个必填字段,清空它的数据并将数据+模式发送到 AJV 进行验证(AJV 而不是 tv4,因为它的解析速度更快)。
通过这样做,我们可以单独知道给定数据需要哪个必填字段。
这些是我们提出的工作函数(不是最干净的,但有助于理解)
function getAllRequiredFields() {
var allRequiredFields = tv4.validateMultiple($scope.formModel, $scope.formSchema).requireds;
allRequiredFields = allRequiredFields.filter(function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
});
return allRequiredFields;
}
function getRequiredFields() {
var t0 = performance.now();
//should be called every model change because of optimization in tv4 for the data+schema.
var allRequiredFields = getAllRequiredFields();
angular.forEach(allRequiredFields, function (requiredPath) {
var modelWithDeletedRequiredProperty = angular.copy($scope.formModel);
deleteValue(modelWithDeletedRequiredProperty, requiredPath);
if (!validateForm(modelWithDeletedRequiredProperty)) {
var requiredError = getErrorObjectsArray(validateForm.errors).find(function (error) {
return error.path === requiredPath;
});
if (requiredError) {
localValidation[requiredError.inputName] = localValidation[requiredError.inputName] || {};
localValidation[requiredError.inputName].isRequired = true;
requiredFieldsPath.push(requiredError.inputName);
}
}
});
var t1 = performance.now();
console.log("form checking took " + (t1 - t0) + " milliseconds.");
}
我需要从 JSON-Schema+Data 中获取必填字段的列表。
目前,我们正在使用 AJV 通过 JSON 架构在我们的表单中获取错误消息,并且效果很好。
我需要一种方法来获取所有必填字段(即使已填写),以便将那些带有 * 的字段标记为 "required"。必填字段可能会根据架构和数据组合而变化。
也曾尝试破解 tv4 来提取所需的字段,但没有成功。
请帮忙。
此类模式的示例:
{
"type": "object",
"required": [
"checkbox"
],
"properties": {
"checkbox": {
"type": "boolean"
},
"textbox": {
"type": "string"
}
},
"oneOf": [
{
"required": [
"textbox"
],
"properties": {
"checkbox": {
"enum": [
true
]
}
}
},
{
"properties": {
"checkbox": {
"enum": [
false
]
}
}
}
],
"additionalProperties": false
}
此函数以递归方式抓取模式索引,因此也许您可以稍微调整一下
// https://github.com/pubkey/rxdb/blob/master/src/rx-schema.js
export function getIndexes(jsonID, prePath = '') {
let indexes = [];
Object.entries(jsonID).forEach(entry => {
const key = entry[0];
const obj = entry[1];
const path = key === 'properties' ? prePath : util.trimDots(prePath + '.' + key);
if (obj.index)
indexes.push([path]);
if (typeof obj === 'object' && !Array.isArray(obj)) {
const add = getIndexes(obj, path);
indexes = indexes.concat(add);
}
});
if (prePath === '') {
const addCompound = jsonID.compoundIndexes || [];
indexes = indexes.concat(addCompound);
}
indexes = indexes
.filter((elem, pos, arr) => arr.indexOf(elem) === pos); // unique;
return indexes;
}
重读您的问题最简单的方法是
- 在页面加载时获取 Json 数据,
- 迭代 json 数据以删除有效值(参见 示例 1),
- 调用tv4.validateMultiple(数据、模式),
- 检查结果对象并获取必填字段(参见示例 2)。
样本 1
for(let prop in data) {
if(data.hasOwnProperty(prop) {
//set value to null, -1, or some other universally bad value
data[prop]...value = null;
}
}
样本 2
let result = tv4.validateMultiple(data, schema);
let required = result.errors;
我们解决了这个问题:
分叉 tv4(tv4 - 因为它很容易编辑):
https://github.com/mikila85/tv4
正在输出一个 "Requireds".
的数组
我们迭代了每个必填字段,清空它的数据并将数据+模式发送到 AJV 进行验证(AJV 而不是 tv4,因为它的解析速度更快)。
通过这样做,我们可以单独知道给定数据需要哪个必填字段。
这些是我们提出的工作函数(不是最干净的,但有助于理解)
function getAllRequiredFields() {
var allRequiredFields = tv4.validateMultiple($scope.formModel, $scope.formSchema).requireds;
allRequiredFields = allRequiredFields.filter(function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
});
return allRequiredFields;
}
function getRequiredFields() {
var t0 = performance.now();
//should be called every model change because of optimization in tv4 for the data+schema.
var allRequiredFields = getAllRequiredFields();
angular.forEach(allRequiredFields, function (requiredPath) {
var modelWithDeletedRequiredProperty = angular.copy($scope.formModel);
deleteValue(modelWithDeletedRequiredProperty, requiredPath);
if (!validateForm(modelWithDeletedRequiredProperty)) {
var requiredError = getErrorObjectsArray(validateForm.errors).find(function (error) {
return error.path === requiredPath;
});
if (requiredError) {
localValidation[requiredError.inputName] = localValidation[requiredError.inputName] || {};
localValidation[requiredError.inputName].isRequired = true;
requiredFieldsPath.push(requiredError.inputName);
}
}
});
var t1 = performance.now();
console.log("form checking took " + (t1 - t0) + " milliseconds.");
}