【问题标题】:Json schema validation against Json Object using javascript使用 javascript 对 Json 对象进行 Json 模式验证
【发布时间】:2021-02-19 05:59:01
【问题描述】:

我正在尝试针对 JSON 架构验证大约 100 个 JSON 对象,以查看所有字段以及类型是否符合架构。

在从站点生成的 JSON 架构下进行了尝试。 以下架构的问题在于它不支持验证“文件”字段的多个项目,因为架构不完全正确。

在架构下方添加

     var schema ={
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "contents": {
          "type": "array",
          "items": [
            {
              "type": "object",
              "properties": {
                "version": {
                  "type": "string"
                },
                "sequence": {
                  "type": "integer"
                },
                "files": {
                  "type": "array",
                  "items": [
                    {
                      "type": "object",
                      "properties": {
                        "fileName": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "fileSize": {
                          "type": "string"
                        },
                        "fileType": {
                          "type": "string"
                        },
                        "lastUpdatedDate": {
                          "type": "integer"
                        },
                        "fileLength": {
                          "type": "integer"
                        },
                        "version": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "fileName",
                        "name",
                        "fileSize",
                        "fileType",
                        "lastUpdatedDate",
                        "fileLength",
                        "version"
                      ]
                    }
                  ]
                }
              },
              "required": [
                "version",
                "sequence",
                "files"
              ]
            }
          ]
        }
      },
      "required": [
        "contents"
      ]
    }
  },
  "required": [
    "data"
  ]
}

  var validator = new Validator(schema)

  var json=
  {
      "data": {
          "contents": [
              {
                  "versionn": "2021-01-15T16:01:13.475Z",
                  "sequence": 1,
                  "files": [
                      {
                          "fileName": "us-producer-price-index.txt",
                          "name": "us-producer-price-index",
                          "fileSize": "54MB",
                          "fileType": "txt",
                          "lastUpdatedDate": 1610717473000,
                          "fileLength": 56614933,
                          "version": 2
                      }
                  ]
              }
          ]
      }
  };

  var check = validator.check(json);
   
  console.log(check);

  if(check._error==true)
  {
      console.log("Error in schema")
  }

【问题讨论】:

  • 您的 JSON 无效。
  • @RichardRublev 架构无效?你能建议改变吗
  • @RichardRublev 添加了有效的模式,仍然是相同的输出

标签: javascript node.js json jsonschema json-schema-validator


【解决方案1】:

虽然您的 JSON 架构是“有效的”,但它不表达任何约束。

您错过了使用 properties 关键字的需要。

“属性”的值必须是一个对象。 this的每个值
对象必须是有效的 JSON 架构。

如果对于同时出现在
中的每个名称,验证成功 实例并作为此关键字值中的名称,child
该名称的实例已成功验证
对应的架构。

https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-02#section-9.3.2.1

为了将子模式应用于对象,您需要使用properties 关键字。像这样……

{
  "required": ["data"],
  "properties": {
    "data": {
      "type": "object"
    }
  }
}

此要求也适用于每个子模式。未知关键字被忽略,因此架构根部的data 被简单地忽略,导致不表达任何约束。

查看 JSON Schema 入门指南可能会对您有所帮助:http://json-schema.org/learn/


更新: 以答案的形式为您的问题添加更新后,看起来生成器几乎是正确的,但并不完全正确。

使用 items 关键字 pre draft 2020-12 时,数组值仅将子模式项应用于相同的索引位置。如果您希望子模式值应用于适用数组中的所有项目,则需要使用模式对象作为值,而不是模式值数组。

“items”的值必须是有效的 JSON Schema 或数组
有效的 JSON 模式。

如果“items”是一个模式,则验证成功,如果所有元素在 数组已成功验证该架构。

如果“items”是一个模式数组,则验证成功,如果每个
实例的元素同时针对架构进行验证
位置,如果有的话。

JSON 架构草案 2019-09 - https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-02#section-9.3.1.1

请参阅上面链接的入门指南,其中涵盖了这一点。如果您希望维护您的架构,那么值得一读。

【讨论】:

  • 谢谢,我想你有我的答案 :) 我也添加了属性键,但它似乎并没有做出任何改变。请求您是否可以为我的 json 添加架构以帮助我理解。谢谢
  • 如果您修改了架构但仍然无法正常工作,您应该考虑更新您的问题以添加新架构。如果我看不到完整的新架构,我不知道如何为您提供帮助。
  • 我现在修改了我的问题。只对如何处理 json 子部分的属性感到困惑
  • 我可以看到您已经更新了您的问题。看来您没有遵循我使用 properties 关键字的建议。您还发布了自己的答案,您可以在其中了解如何在要将子模式应用于更多属性值的每个子模式中使用 properties 关键字。您使用的模式生成器产生了一个非常旧的(draft-04)模式。如果contentsfiles 可以在数组值中有多个项目,那么架构也是错误的,不会做你想做的。
  • 我同意您的说法,请您修改我的架构,以便文件可以处理数组中的多个项目,我可以在此处将您的答案标记为正确答案。如果你这样做会很有帮助。谢谢
【解决方案2】:

我假设您想要对数组中的所有项目应用相同的验证规则。

Schema 提供list validationtuple validationlist 验证被指定为 架构,对数组中的任何项目应用相同的规则,tuple 被指定为 架构数组并针对schema.item[i]验证item[i]

请注意,您的 items 架构是一个包含一个元素的数组。这意味着只有第一个元素会根据您的架构进行验证。我假设你想要的是这个架构。

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "properties": {
    "data": {
      "type": "object",
      "properties": {
        "contents": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "version": {
                "type": "string"
              },
              "sequence": {
                "type": "integer"
              },
              "files": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "fileName": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "fileSize": {
                      "type": "string"
                    },
                    "fileType": {
                      "type": "string"
                    },
                    "lastUpdatedDate": {
                      "type": "integer"
                    },
                    "fileLength": {
                      "type": "integer"
                    },
                    "version": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "fileName",
                    "name",
                    "fileSize",
                    "fileType",
                    "lastUpdatedDate",
                    "fileLength",
                    "version"
                  ]
                }
              }
            },
            "required": [
              "version",
              "sequence",
              "files"
            ]
          }
        }
      },
      "required": [
        "contents"
      ]
    }
  },
  "required": [
    "data"
  ]
}

其他示例

为了说明数组验证的工作原理,我创建了一个非常有启发性的片段。

const Ajv = window.ajv7.default;
const ajv = new Ajv({strict: false});

function dumpJson(item){
  const el = document.createElement('pre');
  el.textContent = typeof(item) === 'string' ? item :  JSON.stringify(item)
  document.body.appendChild(el);
  return el;
}

function Test(schema, title){
  const validate = ajv.compile(schema)
  if(title)dumpJson(title).classList.add('title')
  dumpJson(JSON.stringify(schema, null, 2))
  const tester = {
    with: (item) => {
      const el = dumpJson(item)
      if(validate(item)){
        el.classList.add('valid');
      }else{
        el.classList.add('invalid');
      }
      return tester
    }
  }
  return tester;
}

Test({
  "$schema": "http://json-schema.org/draft-07/schema#",
  type: 'array', items: [{type: 'number'}, {type: 'string'}]
}, 'tuple validation: [number]')
.with([0])
.with([0, 1])
.with([0, "a"])
.with([0, "a", {}, [], null, false, true])
Test({
  "$schema": "http://json-schema.org/draft-07/schema#",
  type: 'array', items: [{type: 'number'}]
}, 'tuple validation: [number, string]')
.with([0])
.with([0, 1])
.with([0, "a"])
.with([0, "a", {}, [], null, false, true])

Test({
  "$schema": "http://json-schema.org/draft-07/schema#",
  type: 'array', items: {type: 'number'}
}, 'list validation: number[]')
.with([0])
.with([0, 1])
.with([0, "a"])
.with([0, "a", {}, [], null, false, true])


Test({
  "$schema": "http://json-schema.org/draft-07/schema#",
  type: 'array', items: [{type: 'number'}, {type: 'string'}]
}, 'tuple validation: [number, string]')
.with([0])
.with([0, 1])
.with([0, "a"])
.with([0, "a", {}, [], null, false, true])

Test({
  "$schema": "http://json-schema.org/draft-07/schema#",
  type: 'array', items: {'anyOf': [{type: 'number'}, {type: 'string'}]}
}, 'list validation: (number|string)[]')
.with([0])
.with([0, 1])
.with([0, "a"])
.with([0, "a", {}, [], null, false, true])
.with(['a', 'b', 'c'])
.with(['a', 0])
.with(['a', 0, false])
.valid {
  margin-left: 20px; color: green;
}
.invalid {
  margin-left: 20px; color: red;
}
.title {
  font-size: 2em;
}

body: {
  overflow: scroll;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/7.1.1/ajv7.min.js"></script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 2023-03-23
    相关资源
    最近更新 更多