json模式(draft7)实现应该如何解析在未知关键字中定义的"$ref"


JSON模式测试套件定义了这样的模式,我认为它们是有效的:
{
"tilda~field": {"type": "integer"},
"slash/field": {"type": "integer"},
"percent%field": {"type": "integer"},
"properties": {
"tilda": {"$ref": "#/tilda~0field"},
"slash": {"$ref": "#/slash~1field"},
"percent": {"$ref": "#/percent%25field"}
}
}

以下面的例子为例:

{
"$id": "http://example.com/root.json",
"definitions": {
"A": { "type": "integer" }
},
"properties": {
"$id": {
"type": "string"
},
"attributes": {
"$ref": "#/tilda~0field/slash~1field/$id"
}
},
"tilda~field": {
"$id": "t/inner.json",
"slash/field": {
"$id": {
"$id": "test/b",
"$ref": "document.json"
}
}
}
}

#/tilda~0field/slash~1field/$id/$ref处的$ref解析为以下哪项?

  • http://example.com/root.json/document.json
  • http://example.com/t/document.json
  • http://example.com/t/test/document.json

#/tilda~0field中的哪个$id必须被视为所讨论的$ref的baseURI,以及为什么。

$refs未在未知关键字内进行解析,因为$ref$id仅适用于模式内部。让我们看一个例子,看看我说的是什么意思。

{
"$id": "http://example.com/foo",
"type": "object",
"properties": {
"aaa": {
"const": { "$ref": "#/definitions/bbb" }
},
"bbb": { "$ref": "#/definitions/bbb" }
},
"ccc": { "$ref": "#/definitions/bbb" },
"definitions": {
"bbb": { "type": "string" }
}
}
  • 文档作为一个整体是一个模式,因此/$id可以用JSON模式来理解
  • properties关键字被定义为一个值为模式的对象。因此,/properties/bbb处的值是一个模式,/properties/bbb/$ref由JSON模式来理解
  • const关键字的值不受约束。/properties/aaa/const中的值可能看起来像一个模式,但它只是一个普通的JSON对象。因此/properties/aaa/const/$ref不能被JSON Schema理解
  • /ccc处的值不是JSONSchema关键字,因此它的值不受约束,也不是模式。因此,JSON Schema无法理解$id$ref关键字

这就是它现在的工作方式。当你回到旧的草案(草案-05 iirc(时,它有点不同。在此之前,$ref是在一个名为JSON引用的单独规范中定义的。JSON架构扩展的JSON引用。因此,$ref的语义适用于JSON模式中出现的所有地方。

编辑:

当已知关键字内的$ref引用未知关键字深处的架构时会发生什么。例如,如果#/properties/bbb引用了#/ccc,该怎么办?

这真是个好问题。引用#/ccc应该是一个错误,因为#/ccc不是架构,而$ref只允许您引用架构。

我刚刚在JSONSchema网站上看到您的问题。我也会在这里发布我在那里发布的内容。不过,也请查看编辑。


以下哪个是#/tilda~0field/slash~1field/$id/$ref处的$ref

我认为第8.2节给出了答案:"子模式的"$id"是根据其父模式的基URI解析的。"这意味着它将http://example.com/t/test/document.json.

#/tilda~0field中的哪些$id必须被视为所讨论的$ref的baseURI,以及为什么。

它的基本URI是根上的$id,由tilda~field中的$id重新路由。

  1. http://example.com/root.json开始
  2. 将文件夹更改为t并使用文件inner.json
  3. 将文件夹更改为test(在t内部(,并使用文件document.json

编辑

看了@customcommander的回复,意识到tilde~field中的值没有作为模式处理,我想说#ref根本不会被处理。它只是一个简单的JSON字符串,没有任何固有的含义。

您确定您的第二个模式有效吗?

例如,根据JSON模式核心规范,$id属性应该是字符串

如果存在,此关键字的值必须是字符串

因此,以下内容在我看来是错误的:

"slash/field": {
"$id": {
"$id": "test/b",
"$ref": "document.json"
}
}

那么我认为你的第一个$ref也不正确:

"attributes": {
"$ref": "#/tilda~0field/slash~1field/$id"
}

它可能应该是:

"attributes": {
"$ref": "#/tilda~0field/slash~1field"
}

同一规范文件也对$id$ref进行了说明:参见本例

"$id"关键字定义了架构的URI,以及解析架构中其他URI引用的基本URI。

或者Ajv简单地说:

$ref被解析为uri引用,使用schema$id作为基本uri[…]。

考虑到您的模式的当前状态,我只能大致回答您的问题,但ref可能会解析为类似t/inner.json#document.json的内容

最新更新