JSON Schema:使用 require 读取文件时删除多个 $ref

kim*_*kim 5 javascript jsonschema

我有一个 json 模式定义了几个属性。我已将其中 2 个属性移至定义,并引用了它们。我这样做是因为我想将它们组合在一起并以通用方式对这些属性进行一些测试。这工作正常,所有 json 数据都像以前一样处理。

但是,我注意到当我将 json 模式文件读入我的 javascript 文件时,我只看到最后一个 $ref。我不知道这是什么原因。我真的需要知道所有引用的属性。

这是我的 json 模式的一个片段(在文件 schemas/schema1.json 中):

{
    "type": "object",
    "properties": {
         "$ref": "#/definitions/groupedProperties/property1",
         "$ref": "#/definitions/groupedProperties/property2"
    },
    "definitions": {
        "groupedProperties": {
            "type": "object",
            "properties": {
                "property1": {
                    "type": "string"
                },
                "property2": {
                    "type": "string"
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我将它读入我的 js 文件中(在文件 test.js 中):

var schemas = requireDir('./schemas')
for (var prop in schemas['schema1'].properties) {
    console.log(prop)
}
Run Code Online (Sandbox Code Playgroud)

当我从我的 js 文件迭代模式中的属性时,我只能看到一个 $ref。我想这是因为它认为属性名称是 '$ref' 并且只能有唯一的名称。是否有某种方式我需要需要这个文件,以便第一个 $ref 不会被破坏?

编辑:我的语法没有通过 json 模式验证器,虽然我不确定为什么,所以我决定做一些不同的事情,而不是为此而苦苦挣扎。我想要的只是一种对某些属性进行分组的方法,因此我将这些属性放回到主模式中,并将定义更改为仅包含该组的属性名称的枚举。所以现在我的架构看起来像:

{
    "type": "object",
    "properties": {
        "property1": {
            "type": "string"
        },
        "property2": {
            "type": "string"
        }
    },
    "definitions": {
        "groupedProperties": {
            "enum": ["property1", "property2"]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在我的 js 文件中:

var myGroup = (schema.definitions ? schema.definitions.groupedProperties : [])
console.log(myGroup.enum) // [ 'property1', 'property2' ]
Run Code Online (Sandbox Code Playgroud)

Jas*_*ers 6

您如何引用定义存在很多问题。

JSON 对象不能有重复的属性

JSON 或 JavaScript 对象中的所有属性都是唯一的。第二个将覆盖第一个。考虑访问属性的语法以了解原因。当您将 JSON 读入 JavaScript 对象时,您可以尝试$ref使用schema.properties['$ref']. 如果有两个,你会得到哪一个(或两个)?JavaScript 没有机制来区分,因为它是不允许的。

$ref 必须独立

$ref在一个对象时,它必须在该对象的唯一属性。所有其他属性将被忽略。这只是为什么有两个$refs 不起作用的另一个原因。

JSON 引用对象中除“$ref”之外的任何成员都应被忽略。

$ref 不应该用于 properties

$ref应该只用于引用模式。在这种情况下,properties关键字 using $refwhich 是具有模式值的对象。$refJSON Schema 或 JSON Reference 的文档中并未明确禁止以这种方式使用,但它不是惯用的 JSON Schema,因此大多数验证器都不支持。即使您使用的验证器确实支持这样的引用,也应该避免这样做,因为它从来没有必要,并且会使架构混乱且难以维护。

你的 JSON 指针是错误的

您的 JSON 指针实际上并不指向您定义的模式。正确的指针是#/definitions/groupedProperties/properties/property1.

可能的解决方案

这就是你想要做的。

{
   "type": "object",
   "properties": {
        "property1": { "$ref": "#/definitions/groupedProperties/properties/property1" },
        "property2": { "$ref": "#/definitions/groupedProperties/properties/property2" }
   },
   "definitions": {
       "groupedProperties": {
           "type": "object",
           "properties": {
               "property1": {
                   "type": "string"
               },
               "property2": {
                   "type": "string"
               }
           }
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

这是一次包含所有内容的更简洁的方法groupedProperties

{
    "type": "object",
    "allOf": [
        { "$ref": "#/definitions/groupedProperties" }
    ],
    "definitions": {
        "groupedProperties": {
            "type": "object",
            "properties": {
                "property1": {
                    "type": "string"
                },
                "property2": {
                    "type": "string"
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,由于您仅将它用于测试目的,您可以翻转它以便定义引用模式。您可以在测试中使用该定义,而不会影响您的架构。

{
    "type": "object",
    "properties": {
        "property1": { "type": "string" },
        "property2": { "type": "string" }
    },
    "definitions": {
        "groupedProperties": {
            "type": "object",
            "properties": {
                "property1": { "$ref": "#/properties/property1" },
                "property2": { "$ref": "#/properties/property2" }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


tea*_*cup 0

这与 无关require,对象键不是唯一的(因为您可以在一个对象中多次声明它们),但它们是可重写的(就像声明两次的变量可重写一样)。您只会收到在两个同名键上声明的最后一个值。

我建议给参考文献一个可区分的 ID,这也有助于代码扩展时的清晰度