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

JSON Schema: multiple $ref get removed when reading file with require

我有一个 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"
                }
            }
        }
    }
}

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

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

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

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

{
    "type": "object",
    "properties": {
        "property1": {
            "type": "string"
        },
        "property2": {
            "type": "string"
        }
    },
    "definitions": {
        "groupedProperties": {
            "enum": ["property1", "property2"]
        }
    }
}

然后在我的js文件中:

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

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

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

您引用定义的方式存在很多问题。

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

###$ref必须独立 当在对象中使用 $ref 时,它必须是该对象中唯一的 属性。所有其他属性将被忽略。这只是两个 $ref 不起作用的另一个原因。

Any members other than "$ref" in a JSON Reference object SHALL be ignored.

###$ref 不应在 properties 中使用 $ref 应该只用于引用模式。在这种情况下,properties 关键字使用 $ref,这是一个具有模式值的对象。 JSON Schema 或 JSON Reference 的文档中并未明确禁止以这种方式使用 $ref,但它不是惯用的 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"
               }
           }
       }
   }
}

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

{
    "type": "object",
    "allOf": [
        { "$ref": "#/definitions/groupedProperties" }
    ],
    "definitions": {
        "groupedProperties": {
            "type": "object",
            "properties": {
                "property1": {
                    "type": "string"
                },
                "property2": {
                    "type": "string"
                }
            }
        }
    }
}

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

{
    "type": "object",
    "properties": {
        "property1": { "type": "string" },
        "property2": { "type": "string" }
    },
    "definitions": {
        "groupedProperties": {
            "type": "object",
            "properties": {
                "property1": { "$ref": "#/properties/property1" },
                "property2": { "$ref": "#/properties/property2" }
            }
        }
    }
}