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

时间:2018-12-01 12:18:49

标签: json schema jsonschema

JSON-Schema-Test-Suite定义了这样的模式,我认为它们是有效的:

{
    "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"
            }
        }
    }
}

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

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

3 个答案:

答案 0 :(得分:3)

$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
  • 整个文档是一个架构,因此properties被JSON Schema理解。
  • /properties/bbb关键字被定义为一个值为架构的对象。因此,/properties/bbb/$ref处的值是一个架构,JSON架构可以理解const
  • /properties/aaa/const关键字的值不受限制。 /properties/aaa/const/$ref处的值可能看起来像一个架构,但它只是一个普通的JSON对象。因此,JSON架构无法理解/ccc
  • $id的值不是JSON Schema关键字,因此它的值不受约束,也不是模式。因此,JSON架构无法理解$ref$ref关键字。

现在就是这样。当您返回较早的草稿(草稿-05 iirc)时,情况有所不同。在此之前,$ref是在称为JSON参考的单独规范中定义的。 JSON模式扩展的JSON参考。因此,$ref的语义在JSON模式中出现的任何地方都适用。

编辑:

  

当已知关键字中的#/properties/bbb引用某个未知关键字内部的模式时会发生什么。例如,如果#/ccc引用了#/ccc,怎么办?

这是一个非常好的问题。引用#/ccc应该是错误的,因为$ref不是架构,而app.intent("late drop", (conv,{term,year}) => { var date = new Date(); var month; if(term == null){ month = date.getMonth(); if(month >= 9 && month <=12){ term = "fall"; //console.log("fall") } else if (month >= 1 && month <= 5) { term = "spring"; //console.log("spring") } else { term = "summer"; //console.log("summer") } } if(year == null){ yearDig = date.getFullYear(); year = yearDig; //console.log(year) } var strYear = year.toString(); var semester = term+strYear.substr(2); const options = { uri: `https://www.registrar.psu.edu/academic_calendar/${semester}.cfm`, transform: function (body) { return cheerio.load(body); } }; rp(options) .then(($) => { let map = {}; let columnOne = []; let columnThree = []; $('table').find('tr td:nth-child(1)').each(function (index, element) { columnOne.push($(element).text()); }); $('table').find('tr td:nth-child(3)').each(function (index, element) { columnThree.push($(element).text()); }); columnOne.forEach((item, i) => { map[item] = columnThree[i]; }); console.log(map); date = map["2Late Drop Begins"]; conv.ask("The late drop period begins on " + map["2Late Drop Begins"]) }) .catch((error) => { console.log(error); conv.ask("An error occured, please try again."); }) 仅允许您引用架构。

答案 1 :(得分:1)

我刚刚在JSON Schema网站上看到了您的问题。我也会在这里发布我发布的内容。但是,也请查看编辑。


  

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

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

  

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

此操作的基本URI是根上的$id,由tilda~field中的http://example.com/root.json重新路由。

  1. t开始。
  2. 将文件夹更改为inner.json,并使用文件test
  3. 将文件夹更改为t(在document.json内部)并使用文件tilde~field

编辑

在查看@customcommander的答复并意识到#ref中的值未作为架构进行处理时,我想说$ref根本不会被处理。这只是一个纯JSON字符串,没有任何内在含义。

答案 2 :(得分:0)

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

例如,根据JSON Schema Core specification$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进行了说明: Cf this example

  

“ $ id”关键字定义架构的URI,以及解析架构中其他URI引用所依据的基本URI。

或者就像Ajv所说的那样:

  

$ ref使用模式$ id作为基本URI […]解析为uri引用。

鉴于您的架构的当前状态,我只能近似回答您的问题,但是参考可能会解决类似t/inner.json#document.json

的问题