最后一个重大变更
在我们继续走向稳定的规范时,我们一直在分析 JSON Schema 的各个组件、行为和功能,以确定哪些可以包含、哪些可能需要修改以及哪些(如果有的话)需要删除或替换。我们主要的问题是,是否会进行任何可能导致使用现有模式的用户出现问题的计划变更,即重大变更。
为了回答这个问题,我们需要用户的反馈。因此,我们在互联网上发布了消息,以鼓励用户参与GitHub 上的特定讨论,讨论我们如何处理即将发布版本中任何可能的重大变更。反应非常一致,即“如果可以,请不要破坏现有功能”。但许多人还表示,如果有一个明确的迁移路径和工具来帮助他们,他们就不会那么担心。
我们还对功能稳定性进行了内部调查,调查对象是所有 JSON Schema 核心团队成员。我们很高兴地报告,Draft 2020-12 的绝大部分内容可以完全保留。有一些关键字和行为可能需要进行一些调整,但大多数情况下,我们认为这些调整与当前版本基本兼容。
用户和团队成员的另一个共同观点是,JSON Schema 已经有了包含重大变更的历史(和声誉),这意味着在发布规范的新版本时,一个在某个版本中能正确验证的模式可能在下一个版本中就无法正确验证。我们需要解决这种认知。为此,我们需要调整自身和规范,以便我们可以承诺,针对某个版本编写的模式将在所有后续版本中始终如一地验证。
不幸的是,为了实现这一承诺,我们必须以一种破坏性的方式更改一种行为:对未知关键字的支持。
什么是未知关键字?
如果一个关键字是在模式的元模式(由 $schema
中的值标识)中列出的词汇表中定义的,则该关键字是“已知”的。通过识别这个词汇表并继续处理模式,实现声明它理解如何处理该词汇表定义的所有关键字。任何未在模式的元模式中列出的词汇表中定义的关键字都被认为是“未知”的。
所有当前发布的 JSON Schema 版本都指示实现(至少)忽略未识别的关键字。随着 Draft 2019-09 中引入注释,实现获得了收集未知关键字的值并将其报告给用户作为输出的选项。这种行为得到了社区的广泛支持,因为这意味着他们可以对模式进行注释和记录,而不必担心验证会受到影响。对于像这样的模式
验证器将要么忽略 database-field-id
,要么将其和它的值作为注释包含在输出中。可以看出,此功能将非常有用。但是,此功能也阻止了我们实现未来兼容性承诺的能力。
为什么我们不能继续支持它?
假设一个用户在使用符合 2023 年规范版本的验证器时编写了上面的示例模式。几年后,他们想升级验证器,现在支持 2025 年规范。然而,在 2025 年规范中,我们添加了 database-field-id
作为关键字,其值预期为字符串。突然,用户的模式不再有效。 我们通过添加新关键字破坏了一个用户。
为了防止这种情况发生,我们被迫禁止未由列出的词汇表声明的关键字。我们认识到,这将从一开始就让很多人感到沮丧。然而,我们认为未来兼容规范的承诺应该优先于立即改变你的模式(以及可能在将来永久地改变你的模式)所带来的痛苦。
正在采取哪些措施来减轻这种冲击?
我们有一个关于这个话题的 公开讨论,我们邀请你参与。
目前的建议包括从简单地为未知关键字添加前缀作为约定来指示自定义注释,到更复杂的解决方案,比如内联和自建词汇表捆绑到模式中,这些词汇表可以定义仅用于注释的关键字,比如 title
和 readOnly
。这些选项实际上是让模式作者说,“我知道这些关键字没有被任何词汇表声明,但我真的很想在我的模式中使用它们。请忽略它们。”
下一个版本中还会有一些其他重大更改吗?
希望不会。我们认为,移除对未知关键字的支持将是唯一一个真正产生负面影响的更改,但这并不排除其他可能以不太关键的方式破坏事物的更改。
我们认识到,进行像这样的重大更改对于开发者(用户和实现者)来说都很困难,因此我们正在尽力衡量所需的更改并寻求可能的替代方案。我们不认为这是一个肆意改变的机会。
无论如何,我们将对我们做出的任何更改(包括破坏性的和非破坏性的)保持公开和透明。
总结
看起来我们必须在下一个版本中破坏一些模式。然而,通过这样做,我们可以保证将来不会再这样做了。
我们必须打破它才能修复它。
封面图片由 Ken Suarez 在 Unsplash 上提供