简体   繁体   English

JSON Schema提取必填字段

[英]JSON Schema extract the required fields

I need to get a list of the required fields out of a JSON-Schema+Data. 我需要从JSON-Schema + Data中获取所需字段的列表。

Currently, we are using AJV to get error messages in our forms with JSON Schema and it is working great. 目前,我们正在使用AJV在我们的表单中使用JSON Schema获取错误消息,并且它运行良好。

I need a way to get all the required fields (even if filled) in order to mark those fields with * as "required". 我需要一种方法来获取所有必需的字段(即使已填充),以便将这些字段标记为*为“required”。 required fields might change depending on the schema and data combinations. 必填字段可能会更改,具体取决于架构和数据组合。

Also tried hacking tv4 to extract the required fields without success. 还试图通过黑客攻击tv4来提取所需的字段但没有成功。

Please help. 请帮忙。


Example for such schema: 此类架构的示例:

{
  "type": "object",
  "required": [
    "checkbox"
  ],
  "properties": {
    "checkbox": {
      "type": "boolean"
    },
    "textbox": {
      "type": "string"
    }
  },
  "oneOf": [
    {
      "required": [
        "textbox"
      ],
      "properties": {
        "checkbox": {
          "enum": [
            true
          ]
        }
      }
    },
    {
      "properties": {
        "checkbox": {
          "enum": [
            false
          ]
        }
      }
    }
  ],
  "additionalProperties": false
}

Rereading your question the easiest way to do what you'd like would be to 重读你的问题是做你想做的最简单的方法

  1. get the Json data on page load, 在页面加载时获取Json数据,
  2. iterate over the json data to remove valid values (see sample 1 ), 迭代json数据以删除有效值(参见示例1 ),
  3. Call tv4.validateMultiple(data, schema), 调用tv4.validateMultiple(data,schema),
  4. check the result object and get the required fields (see sample 2 ). 检查结果对象并获取必填字段(参见示例2 )。

sample 1 样品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;
    }
}

sample 2 样本2

let result = tv4.validateMultiple(data, schema);
let required = result.errors;

We solved it by: 我们解决了它:

  1. Forking tv4 (tv4 - because it was easy to edit): 分叉tv4(tv4 - 因为它很容易编辑):

    https://github.com/mikila85/tv4 https://github.com/mikila85/tv4

    outputting an array of "Requireds". 输出“Requireds”数组。

  2. We itereted each required field, emptying it's data and sending data+schema to AJV for validation (AJV and not tv4 because its faster at parsing). 我们迭代了每个必需的字段,清空它的数据并将数据+模式发送到AJV进行验证(AJV而不是tv4,因为它在解析时速度更快)。

By doing that we could know individually which required field is required for the given data. 通过这样做,我们可以分别知道给定数据所需的字段。

these are the working functions we came out with (not the cleanest but will help get the idea) 这些是我们提出的工作功能(不是最干净但有助于理解)

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.");
}

This function grabs schema indices recursively, so maybe you could adapt it a little 这个函数递归地抓取模式索引,所以也许你可以调整一下

   // 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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM