如何使 json $ref 指向本地文件?
How do you make json $ref to local files?
我在我的 node.js 项目中使用 AJV 包。
我正在尝试根据几个模式文件验证一些数据。这两个模式文件都在同一目录中:
/dir
|
parent_schema.json
|
sub_schema.json
/data
|
data.json
我正在尝试获取 $ref
属性 工作的超级简单示例,但我遇到了麻烦。 parent_schema.json
看起来像:
{
"properties": {
"foo": { "type": "string" },
"bar": { "$ref": "sub_schema.json" }
}
}
而 sub_schema.json
看起来像:
{
"properties": {
"sub1": { "type": "string" },
}
}
我正在尝试验证我的 data.json
,为了完整起见,它看起来像:
{
"foo": "whatever",
"bar": {
"sub1": "sometext"
}
}
我遇到的问题是我的 $ref
路径。我从 AJV 收到此错误:
MissingRefError {
message: "can't resolve reference subschema1.json from id #"
missingRef: "subschema1.json"
missingSchema: "subschema1.json"
}
有人看到我的路径有什么问题吗?我知道您还应该使用 #
到 select 您想要匹配的特定 属性,但我希望使用整个模式。
一个常见的误解是 $ref
以某种方式 "loads" 一个文件。
看看ajv.js.org怎么说:
$ref is resolved as the uri-reference using schema $id as the base URI (see the example).
并且:
You don’t have to host your schema files at the URIs that you use as schema $id. These URIs are only used to identify the schemas, and according to JSON Schema specification validators should not expect to be able to download the schemas from these URIs.
Ajv 不会尝试从 stack://over.flow/string
加载此模式,例如:
{
"$id": "stack://over.flow/string",
"type": "string"
}
如果您想在另一个模式中引用该模式,它们都需要具有相同的基本 URI stack://over.flow/
例如,
{
"$id": "stack://over.flow/object",
"type": "object",
"properties": {
"a": { "$ref": "string#" }
}
}
这里 { "$ref": "string#" }
说 "import the schema at stack://over.flow/string" 所以你最终得到:
{
"$id": "stack://over.flow/object",
"type": "object",
"properties": {
"a": {
"$id": "stack://over.flow/string",
"type": "string"
}
}
}
这允许您组合小模式:
const ajv = new Ajv;
ajv.addSchema({
"$id": "stack://over.flow/string",
"type": "string"
});
ajv.addSchema({
"$id": "stack://over.flow/number",
"type": "number"
});
const is_string = ajv.getSchema("stack://over.flow/string");
const is_number = ajv.getSchema("stack://over.flow/number");
console.log(is_string('aaa'), is_string(42));
console.log(is_number('aaa'), is_number(42));
const is_ab = ajv.compile({
"$id": "stack://over.flow/object",
"type": "object",
"properties": {
"a": { "$ref": "string#" },
"b": { "$ref": "number#" }
}
});
console.log(is_ab({a: "aaa", b: 42}));
console.log(is_ab({a: 42, b: "aaa"}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/6.12.2/ajv.min.js"></script>
(请注意,在您的示例中,两个模式都不正确。您在两个模式中都缺少 {"type": "object"}
。)
回答你的问题:
const ajv = new Ajv;
ajv.addSchema({
"$id": "stack://over.flow/parent.schema",
"type": "object",
"properties": {
"foo": { "type": "string" },
"bar": { "$ref": "child.schema#" }
}
});
ajv.addSchema({
"$id": "stack://over.flow/child.schema",
"type": "object",
"properties": {
"sub1": { "type": "string" },
}
});
const is_parent = ajv.getSchema("stack://over.flow/parent.schema");
const is_child = ajv.getSchema("stack://over.flow/child.schema");
console.log(is_parent({
"foo": "whatever",
"bar": {
"sub1": "sometext"
}
}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/6.12.2/ajv.min.js"></script>
我在我的 node.js 项目中使用 AJV 包。
我正在尝试根据几个模式文件验证一些数据。这两个模式文件都在同一目录中:
/dir
|
parent_schema.json
|
sub_schema.json
/data
|
data.json
我正在尝试获取 $ref
属性 工作的超级简单示例,但我遇到了麻烦。 parent_schema.json
看起来像:
{
"properties": {
"foo": { "type": "string" },
"bar": { "$ref": "sub_schema.json" }
}
}
而 sub_schema.json
看起来像:
{
"properties": {
"sub1": { "type": "string" },
}
}
我正在尝试验证我的 data.json
,为了完整起见,它看起来像:
{
"foo": "whatever",
"bar": {
"sub1": "sometext"
}
}
我遇到的问题是我的 $ref
路径。我从 AJV 收到此错误:
MissingRefError {
message: "can't resolve reference subschema1.json from id #"
missingRef: "subschema1.json"
missingSchema: "subschema1.json"
}
有人看到我的路径有什么问题吗?我知道您还应该使用 #
到 select 您想要匹配的特定 属性,但我希望使用整个模式。
一个常见的误解是 $ref
以某种方式 "loads" 一个文件。
看看ajv.js.org怎么说:
$ref is resolved as the uri-reference using schema $id as the base URI (see the example).
并且:
You don’t have to host your schema files at the URIs that you use as schema $id. These URIs are only used to identify the schemas, and according to JSON Schema specification validators should not expect to be able to download the schemas from these URIs.
Ajv 不会尝试从 stack://over.flow/string
加载此模式,例如:
{
"$id": "stack://over.flow/string",
"type": "string"
}
如果您想在另一个模式中引用该模式,它们都需要具有相同的基本 URI stack://over.flow/
例如,
{
"$id": "stack://over.flow/object",
"type": "object",
"properties": {
"a": { "$ref": "string#" }
}
}
这里 { "$ref": "string#" }
说 "import the schema at stack://over.flow/string" 所以你最终得到:
{
"$id": "stack://over.flow/object",
"type": "object",
"properties": {
"a": {
"$id": "stack://over.flow/string",
"type": "string"
}
}
}
这允许您组合小模式:
const ajv = new Ajv;
ajv.addSchema({
"$id": "stack://over.flow/string",
"type": "string"
});
ajv.addSchema({
"$id": "stack://over.flow/number",
"type": "number"
});
const is_string = ajv.getSchema("stack://over.flow/string");
const is_number = ajv.getSchema("stack://over.flow/number");
console.log(is_string('aaa'), is_string(42));
console.log(is_number('aaa'), is_number(42));
const is_ab = ajv.compile({
"$id": "stack://over.flow/object",
"type": "object",
"properties": {
"a": { "$ref": "string#" },
"b": { "$ref": "number#" }
}
});
console.log(is_ab({a: "aaa", b: 42}));
console.log(is_ab({a: 42, b: "aaa"}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/6.12.2/ajv.min.js"></script>
(请注意,在您的示例中,两个模式都不正确。您在两个模式中都缺少 {"type": "object"}
。)
回答你的问题:
const ajv = new Ajv;
ajv.addSchema({
"$id": "stack://over.flow/parent.schema",
"type": "object",
"properties": {
"foo": { "type": "string" },
"bar": { "$ref": "child.schema#" }
}
});
ajv.addSchema({
"$id": "stack://over.flow/child.schema",
"type": "object",
"properties": {
"sub1": { "type": "string" },
}
});
const is_parent = ajv.getSchema("stack://over.flow/parent.schema");
const is_child = ajv.getSchema("stack://over.flow/child.schema");
console.log(is_parent({
"foo": "whatever",
"bar": {
"sub1": "sometext"
}
}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/6.12.2/ajv.min.js"></script>