【问题标题】:json schema property description and "$ref" usagejson 模式属性描述和“$ref”用法
【发布时间】:2016-02-07 11:59:27
【问题描述】:

我正在编写一个 json 架构来验证我由 exe 生成的 json 输出。该架构有点复杂,我定义了一些在属性中引用的“定义”(“$ref”:“#/definitions/. ..)。在这里使用定义更为重要,因为我有一个定义是递归的情况。

我的架构现在运行良好,它可以正确验证我的 json 输出。

现在,我正在尝试为每个属性使用“description”关键字正确记录架构。为了开发模式,我使用了一个以图形方式表示模式的编辑器 (XMLSpy)。很有用,但是遇到了一个奇怪的行为,不知道是编辑器的问题还是我不​​是很懂。

这是解释我的问题的 json 架构的最小示例:

{
	"$schema": "http://json-schema.org/draft-04/schema#",
	"type": "object",
	"properties": {
		"sourcePath": {
			"$ref": "#/definitions/Path",
			"description": "Here the description where I expected to set it"
		},
		"targetPath": {
			"$ref": "#/definitions/Path",
			"description": "Here another description where I expected to set it to that property of the same kind but whith a different use."
		}
	},
	"additionalProperties": false,
	"definitions": {
		"Path": {
			"description": "Here the descriptiond where it is set by the software",
			"type": "object",
			"properties": {
				"aUsefulProperty": {
					"type": "string"
				},
				"parentPath": {
					"$ref": "#/definitions/Path",
					"description": "Here yest another description where I expected to set it.."
				}
			},
			"required": [
				"aUsefulProperty"
			],
			"additionalProperties": false
		}
	}
}

当我尝试向属性添加描述时,编辑器实际上在对象的定义中添加了描述。因此,编辑器会为属性“sourcePath”和“targetPath”显示此描述,此外它还会在“parentPath”中显示此描述。

我的意图是为每个属性提供三种不同的描述(可能还有定义本身,但这不是问题所在)。如果我手动将它们添加到 json 架构中,则没有问题,但这些描述不会出现在图形编辑器中。

所以,我很困惑。

您认为这是我的图形编辑器有问题还是我错了?

基本上,当我们使用“$ref”来定义属性时,是否可以添加一些其他字段作为描述,或者使用“$ref”是否意味着不使用其他任何内容?在这种情况下,如何正确记录属性?

我必须将我的 json 模式提供给一些合作伙伴,他们必须将它们用作文档来生成正确的 json 输出。所以,我想尽可能地为他们提供一个自我记录的 json 模式,就像我们可以使用 XML 一样。

谢谢

【问题讨论】:

    标签: json jsonschema json-schema-validator json-ref


    【解决方案1】:

    JSON 引用对象中除 "$ref" 之外的任何成员都应为 忽略。

    要设置description,您必须执行类似于以下示例的操作。它可能会在您的编辑器中引起其他怪异,但我很确定这是最干净的方法。

    原文:

    {
        "$ref": "#/definitions/Path",
        "description": "Here the description where I expected to set it"
    }
    

    建议更正:

    {
        "allOf": [{ "$ref": "#/definitions/Path" }],
        "description": "Here the description where I expected to set it"
    }
    

    【讨论】:

    • 感谢您的回答。我看到的问题是当我使用诸如“allOf”或“oneOf”之类的运算符时,使用此运算符的对象必须重复组合模式的所有属性(或者有可能允许任何属性,所以我们不能添加“additionalProperties “: 错误的)。这是当前 json 格式存在的问题,可能会在未来版本中更正。无论如何,只是添加评论有点复杂。但现在我得到了我一直在寻找的答案:当使用“$ref”时,JSON 引用对象中除“$ref”之外的任何成员都应被忽略。谢谢。
    • 我知道你所指的问题,但在这个简单的案例中你不应该遇到任何问题。您描述的问题是为什么在使用 JSON Schema 时,最好忽略其他属性而不是明确禁止它们。
    • 我一般同意,但这里的 json 将由接收器解析,当出现意外属性时可能会崩溃,所以......(我知道解决方案是更正解析器)。我已经在我的架构中使用了一些运算符作为“allOf”和“anyOf”,但添加评论似乎太复杂了。实际上,我们可能最终选择的解决方案是从 UML 模型(我们已经拥有)生成 json 模式,因此文档和 cmets 最终将在 UML 中。
    • 我同意增加的复杂性对于元数据可能不值得,除非您使用它来生成类似于文档的内容。如果它只是开发团队的注释,它会将其留在$ref 旁边,并让任何工具忽略它。用 UML 方法走运吧。我通常不喜欢生成代码,但我希望它对你有用。如果您喜欢在 UML 中工作,那么将它放在应用程序的中心是有意义的。
    • 这不太对,因为“allOf”是一个数组。必须是"allOf": [ { "$ref": "#/definitions/Path" } ],
    【解决方案2】:

    当前 JSON Schema 草案允许覆盖来自 $refs 的关键字。原始问题中的架构将被视为有效(取决于草案...)

    来自原始帖子

        ...
        "properties": {
            "sourcePath": {
                "$ref": "#/definitions/Path",
                "description": "Here the description where I expected to set it"
            },
            "targetPath": {
                "$ref": "#/definitions/Path",
                "description": "Here another description where I expected to set it to that property of the same kind but whith a different use."
            }
        },
       ...
    

    JSON Schema 规范包括一个identical example

    来自 JSON Schema Draft2019

                ....
                "properties": {
                    "enabled": {
                        "description": "If set to null, Feature B
                                        inherits the enabled
                                        value from Feature A",
                        "$ref": "#/$defs/enabledToggle"
                    }
                }
                ...
    

    问题中的用例正是 JSON Schema 规范所描述的。事实上,您可以覆盖任何注释关键字(即titledescriptiondefaultexamples)。上面链接的示例还显示了覆盖“默认”属性。

    不幸的是,该标准使实现这一点成为可选的。

    应用程序可以决定使用多个注释值中的哪一个 基于贡献值的模式位置。这是为了一个 允许灵活使用。

    所以你应该在依赖它之前测试它。

    【讨论】:

    • 新的$ref 在逻辑上等同于包裹在allOf 中的旧$ref。如果不清楚,$ref 的兄弟关键字不限于注释关键字,仍然没有覆盖任何东西的概念。一个属性将有两个描述,而不是一个覆盖另一个。但是,仅对于注释关键字,实现可以选择使用那些认为合适的注释。这创建了一个足够松散的规范,实现可以在不违反规范的情况下对注释采用一种覆盖类型的行为。
    猜你喜欢
    • 1970-01-01
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多