是否有推荐的方法来构造多个 JSON 模式?

Are there recommended ways to structure multiple JSON schemas?

我刚刚写了我的第一个 JSON 模式,太棒了!但是,我现在正在研究如何构建多个 JSON 模式,包括在开发期间以及之后如何托管它们。这方面的指导似乎非常有限。

当然,我查阅了官方 json-schema.org 文档 on how to structure a complex scheme,甚至得到了 something 来工作。我现在有三个模式,在开发过程中以文件夹结构组织如下:

json-schemas
  - /common
    - /common-schemas.json
  - /data
    - /data-schemas.json
    - /DataStreamServiceRequest
      - /DataStreamServiceRequest-schema.json

在这三个中,只有 DataStreamServiceRequest-schema.json contains a single schema (it is a schema for all possible requests to an application service endpoint). It refers to types defined in data-schemas.json and common-schemas.json 使用相对引用。此处的目的是在一个文件中提供单个子系统(例如 data)的所有类型。

我为所有三个 .json 文件分配了一个包含绝对 URI 的 $id,对应于它们所在的目录。

例如这里是common-schemas.json:

{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "$id": "https://carp.cachet.dk/schemas/common",
  "NamespacedId": {
    "type": "string",
    "pattern": "^([a-z_0-9]+\.?)+[a-z_0-9]$"
  }
}

并且,从 data-schemas.json 开始,我在 common-schemas.json 中引用 NamespacedId 使用:

"dataType": { "$ref": "common#/NamespacedId" }

我很高兴这有效,但是,这是推荐的吗?我是否忽略了一些基本的架构结构,如下所示?是否有任何特别的理由更喜欢“每种类型一个模式”?是否有我忽略的惯用结构,例如,相当于 Java 对应于命名空间的文件位置?

如果没有(我会在 Java 中争辩说有)也构成一个答案。

可能还有其他相关上下文:我在初始化验证器时使用 networknt/json-schema-validator, and for development/testing purposes, it is very convenient to not have too many absolute URIs. I need to map each URI to a local file

就像代码组织一样,没有一个正确答案。如果您打算在许多不同的环境中重用特定的模式,将它放在一个单独的文件中是有意义的。但是如果你只打算在一个地方使用它,将它放在同一个文件中的 $defs 下可能会更方便。您甚至可以通过 $anchor.

为该架构指定一个更好的名称来引用它

正如@Ether 所说,没有唯一的正确答案,但这是我使用的准则。

最重要的指南 post 是像对待系统中的任何其他代码一样对待您的架构。通常,这意味着您描述的每个“事物”(“人”、“产品”、“地址”等)都应该有自己的架构。

定义 ($defs) 只能在同一架构中引用 ($ref)。使用定义来提高可读性或减少架构中的重复。任何对外部架构的引用都不应该有 JSON 指针 URI 片段(例如,您使用的 #/$defs/NamespacedId 片段)。如果您需要在外部模式中引用定义,它可能是一个标志,它应该在它自己的模式中。

如果您有一堆微小的模式要放入“common.schema.json”模式,则可能会出现这种情况。在这种情况下,您的所有模式都应定义为定义,但有一个锚 $anchor。它需要是一个定义,以便您可以使用标准工具来验证您的模式是否有效。使用锚点可以让您更轻松地引用它,但更重要的是,这是一个信号,表明某些外部模式可能依赖于它。没有锚点的定义实际上是模式私有的,而带有锚点的定义实际上是 public。您可以自由地重构未锚定的定义,但如果重构锚定的定义,则必须警惕破坏其他模式。

不要使用 $id。当架构没有 $id 时,它由用于检索架构的 URI 标识。这可以是文件 URI (file:///path/to/schemas/person.schema.json)。然后您的所有引用都可以是相对的,这意味着您的模式中没有绝对 URI,并且您不需要配置来将 https URI 映射到文件位置。不幸的是,并非所有实现都支持基于文件的检索甚至检索 URI 标识,因此这并不总是可行的。

以有意义的方式组织您的模式。遵循与任何其他代码相同的直觉和准则。如果必须使用 $ids,请确保路径与文件系统上的路径匹配(例如 https://example.com/schemas/person => file:///local/path/to/app/schemas/person.schema.json)。这只会让您更轻松地找到您要查找的架构。