如何在JSON模式中扩展模式?

Pan*_*agi 1 schema json jsonschema

我正在使用JSON模式进行数据建模。我定义一个基Document模式,即我以后使用来定义模型模式(例如ProductCategoryUser等等)。

我这样做是因为我希望所有模型都继承某些结构/规则。例如每模型实例应当具有某些共同的性质(如,idcreatedAtupdatedAt)。在OOP术语中:Product extends Document因此,它继承其实例属性。在模式中,术语(我认为)Document是用于创建模型模式的元模式。

我已经定义了Document模式,如下所示:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "id": "http://example.com/schemas/document.json#",
  "title": "Document",
  "type": "object",
  "additionalProperties": false,
  "required": ["type", "name", "fields"],
  "properties": {
    "type": {
      "constant": "document"
    },
    "name": {
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "description": {
      "type": "string"
    },
    "readOnly": {
      "type": "boolean"
    },
    "properties": {
      // common properties 
      // model-specific properties
    }
  }
}
Run Code Online (Sandbox Code Playgroud)
  1. 如何指定文档元模式“扩展”的基础架构JSON(草案-07),这样我就不必定义草案(所有属性$schemaid等等)?
  2. 如何指定的properties每个模型架构包含一些常用的属性(idcreatedAt,...),而不必在每个模型的架构定义来定义呢?

Jas*_*ers 9

JSON Schema不使用面向对象的范例,因此继承等概念无法很好地转换。JSON模式是约束的集合。像大多数人习惯的那样,它是减性的而不是加性的。这意味着在给定一个空模式的情况下,有效 JSON文档的集合就是所有 JSON文档的集合。添加关键字时,您将从有效的JSON文档集中减去。从集合中删除某些内容后,将无法重新添加。

因此,您可以使用合成来“扩展”模式,但是永远不能“覆盖”另一个模式定义的内容。

/模式/基础

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" }
    "bar": { "type": "string" }
  }
}
Run Code Online (Sandbox Code Playgroud)

/模式/扩展

{
  "allOf": [{ "$ref": "/schema/base" }],
  "properties": {
    "baz": { "type": "string" }
  }
}
Run Code Online (Sandbox Code Playgroud)

这里有一个简单的扩展,可以很好地与JSON Schema一起使用。

/模式/覆盖

{
  "allOf": [{ "$ref": "/schema/base" }],
  "properties": {
    "bar": { "type": "integer" },
    "baz": { "type": "boolean" }
  }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,两个模式都有一个/properties/bar字段。如果您从继承的角度考虑这一点,那么您会误解这里发生的事情。在这种情况下,两个 “ / properties / bar”字段都必须有效。没有冲突可以解决。正如关键字所说,“所有”模式都必须有效。

希望可以为您提供足够的信息来解决您的问题并避免最常见的陷阱。

  • 这是正确的。一个并不优先于另一个。他们都适用。由于没有可能同时是字符串和整数的 JSON 文档,因此对于该模式,任何内容都不会有效。 (4认同)
  • @Onkeltem 将 `additionalProperties` 替换为 `unevaluatedProperties`,它将按您的预期工作。 (3认同)
  • 当您写“在这种情况下,两个“/properties/bar”字段必须有效”时,您的意思是“bar”必须都是字符串(根据基本模式)*并且*是整数(根据覆盖架构)?既然这是不可能的,任何 JSON 都会因覆盖模式而失败,不是吗? (2认同)
  • 应该注意的是,官方指南特别指出此建议实际上并未扩展任何内容 - https://web.archive.org/web/20201020173257/https://json-schema.org/understanding-json-schema/参考/combining.html#id5 (2认同)
  • @Patrick 如果您使用的是 2019-09 或更高版本的草案,那么您可以省略“allOf”。在 JSON Schema 的早期草案中,如果一个对象中有“$ref”,则它被认为只是一个引用,而不是一个架构。这意味着该引用中的任何 JSON 架构关键字都会被忽略,因为关键字仅在架构中有意义。这实际上意味着“$ref”必须始终是单独的,并且我们需要“allOf”来组合引用和模式。在新版本的“$ref”中,引用是“$ref”关键字的字符串值,而“$ref”的工作方式类似于具有一个模式的“allOf”。 (2认同)