JSON架构:读取带有require的文件时,会删除多个$ref

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

本文关键字:删除 ref 文件 读取 架构 require JSON      更新时间:2023-09-26

我有一个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' ]

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

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

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

除"$ref";在JSON引用对象中已忽略。

  • https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03#section-3

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

###您的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" }
            }
        }
    }
}

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

我建议给refs一个有区别的ID,这也有助于在代码扩展

时保持清晰