在我的JSON序列化数据中,我有嵌套对象:
{
"A" : { "A1": 1,
"A2": 2 },
"B" : { "B1": 3,
"B2": 4 }
}
由于给定的限制我不能影响,我需要压扁结构。这意味着,深度大于1的每个对象都必须编码为字符串。应用于上面的例子,这是这样的:
{
"A" : "\{\"A1\": 1, \"A2\": 2\}"
"B" : "\{\"B1\": 3, \"B2\": 4\}"
}
因为我需要在JSON Schema中表达这个约束,所以我几乎要遵循它的句法规则。我想这些对象的类型可能是string
或object
。
{
"title": "My Schema",
"type": "object",
"properties": {
"A": {
"type": "string vs. object"
"B": {
"type": "string vs. object"
}
答案 0 :(得分:5)
我同意,您选择object
或string
类型。我查看了JSON Schema documentation,我找不到任何可以根据需要表达约束的内容。因此,我想到了对这两种方法的简短讨论。
输入字符串
JSON Schema定义了七种基本类型,包括对象。字符串简单地定义为JSON字符串。 RFC 4627定义了一个JSON字符串,如下所示
字符串是零个或多个Unicode字符的序列
这适用于您的情况,即使必须限制字符串的内容。问题是如何传达限制。我会使用description
来引用另一个子模式。您甚至可以为字符串定义pattern
,并将子模式编码为正则表达式。然而,这将非常容易出错并且根本不可读。但是,它可以用于更好的数据模式验证。
{
"title": "My Schema",
"type": "object",
"properties": {
"A": {
"type": "string".
"description": "Please refer to http://... for the subschema."
},
"B": {
"type": "string"
"description": "Please refer to http://... for the subschema."
}
}
这样做的好处是,JSON提供程序必须将字符串放入该属性是明确无误的。缺点是完整的模式不能被视为一次,描述可能被监督,并且在查找过程中也很麻烦。最后,当看到类型string
但在子模式中定义object
时会非常混乱。
输入对象
通过简单地使用类型,您可以避免使用字符串的所有缺点。这里的问题实际上是说明了必须是字符串编码的描述将被忽略。
{
"title": "My Schema",
"type": "object",
"properties": {
"A": {
"description": "Must be encoded as string",
"type": "object",
"properties": { "A1": { "type": "string" }, "A2": { "type": "string" } }
},
"B": {
"description": "Must be encoded as string",
"type": "object"
"properties": { "A1": { "type": "string" }, "A2": { "type": "string" } }
}
}
你总是可以做一些完全虚假的事情,比如使用类型string
并为它定义properties
,但这将是无效的JSON模式。
我建议您使用类型对象方法。虽然存在这种约束,但使用字符串类型总是会导致其后面的数据降级。可以通过其他方式强制执行约束。观察谁提供数据,将约束传达给所有各方,阻止与此约束无关的数据等。
谁知道,也许这个约束不会永远存在,如果发生变化,你需要在另一种情况下再次更改模式,你只需要删除注释,说明字符串编码的要求。
答案 1 :(得分:1)
我知道你已经选择了一个答案,但我想我只是提到了这里的原则。
JSON Schema试图避免进行“语义”验证 - 因此,它们意味着验证标量类型中的数据(例如强制执行字符串格式或数值精度)。
如果您想记录这样的字符串值的内部格式,您可以使用"format"
值(可能是自定义值,因为标准中没有合适的值)。
...或者您可以使用"media"
。此schema关键字的值是一个对象,它可以具有属性"type"
,该属性指定字符串值的媒体类型。所以你的属性看起来像:
{
"type": "string",
"media": {
"type": "application/json"
}
}
允许验证者忽略"format"
,并且极不可能使用"media"
进行验证(甚至没有提到它),但就描述您的扁平化数据格式而言,"media"
是最准确的方法。
(但是,正如公认的答案所述,将其视为奇怪的序列化方法而非数据约束在许多方面都是更优雅的解决方案。)