JSON Schema提取必填字段

时间:2018-01-02 17:21:07

标签: javascript json jsonschema ajv tv4

我需要从JSON-Schema + Data中获取所需字段的列表。

目前,我们正在使用AJV在我们的表单中使用JSON Schema获取错误消息,并且它运行良好。

我需要一种方法来获取所有必需的字段(即使已填充),以便将这些字段标记为*为“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
}

3 个答案:

答案 0 :(得分:1)

重读你的问题,最简单的方法就是做你想做的事情

  1. 在页面加载时获取Json数据,
  2. 遍历json数据以删除有效值(请参阅示例1 ),
  3. 调用tv4.validateMultiple(data,schema),
  4. 检查结果对象并获取必填字段(请参阅示例2 )。
  5. 样本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;
    

答案 1 :(得分:0)

我们通过以下方式解决了这个问题:

  1. 分叉tv4(tv4 - 因为它很容易编辑):

    https://github.com/mikila85/tv4

    输出“Requireds”数组。

  2. 我们迭代了每个必填字段,清空了它的数据并将数据+模式发送到AJV进行验证(AJV而不是tv4,因为它解析速度更快)。

  3. 通过这样做,我们可以分别知道给定数据所需的字段。

    这些是我们提出的工作功能(不是最干净但有助于理解)

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

答案 2 :(得分:-1)

这个函数递归地抓取模式索引,所以也许你可以稍微调整一下

df <- data.frame(Id = 101:107, 
                 Col1 = c("a-b-c-d", "a-c-d", "a-b", "a-b", "b-a", "b-a", "a-c-b"))

forcats::fct_relabel(df$Col1, 
                     function(levs){
                         sapply(strsplit(levs, '-'), 
                                function(lev) paste(sort(lev), collapse = '-'))
                     })
#> [1] a-b-c-d a-c-d   a-b     a-b     a-b     a-b     a-b-c  
#> Levels: a-b a-b-c-d a-b-c a-c-d

forcats::lvls_revalue(df$Col1, 
                      sapply(strsplit(levels(df$Col1), '-'), 
                             function(x){paste(sort(x), collapse = '-')}))
#> [1] a-b-c-d a-c-d   a-b     a-b     a-b     a-b     a-b-c  
#> Levels: a-b a-b-c-d a-b-c a-c-d