Protocol

Schema

The BAQ Schema format was inspired by JSON Schema­ and JSON Type Definition­. It should look familiar to anyone with experience with either. This new format was introduced to meet the following design goals:

  • Strictness. No additional properties or items. Self-contained schema documents. No implicit behavior: each schema has a well-identified type.
  • Schema evolution. Two versions of a schema can be programmatically compared to ensure back compatibility.
  • Code generation. Closely match the TypeScript type system to automatically generate accurate type definitions.

A BAQ Schema is a union of all the possible schema types. The type is the union discriminator. These properties are common to all schemas:

Properties

Schema for a JSON object with known properties.

{
  "type": "object",
  "properties": {
    "hello": {
      "type": "string"
    },
    "world": {
      "type": "string",
      "optional": true
    }
  }
}

Properties

  • type enum

    • Value: "object"
  • properties {[string]: Schema}

    • Properties of the represented object, and their corresponding schemas.

      Each property value is a Schema­ with this additional property:

      • optional boolean optional

        • Allow the property to be omitted.

          Default: false

Schema for a JSON array.

{
  "type": "array",
  "items": {
    "type": "string"
  }
}

Properties

  • type enum

    • Value: "array"
  • items Schema

    • Schema for the values in the array.
  • min_items int optional

    • Minimum number of items in the array (inclusive).
  • max_items int optional

    • Maximum number of items in the array (inclusive).
  • distinct_items boolean optional

    • Require all items in the array to have distinct values.

      Default: false

Schema for a JSON boolean value.

{
  "type": "boolean"
}

Properties

  • type enum

    • Value: "boolean"
  • enum boolean[] optional

    • Allowed boolean values.

Schema for a JSON string value.

{
  "type": "string"
}

Properties

  • type enum

    • Value: "string"
  • enum string[] optional

    • Allowed string values.
  • min_length int optional

    • Minimum length of the string (inclusive).
  • max_length int optional

    • Maximum length of the string (inclusive).

Notes

Schema for a JSON integer number.

{
  "type": "int"
}

Properties

  • type enum

    • Value: "int"
  • enum int[] optional

    • Allowed integer values.
  • min int optional

    • Minimum value of the integer (inclusive).
  • max int optional

    • Maximum value of the integer (inclusive).

Notes

Schema for a JSON floating-point number.

{
  "type": "number"
}

Properties

  • type enum

    • Value: "number"
  • enum number[] optional

    • Allowed number values.
  • min number optional

    • Minimum value of the number (inclusive).
  • max number optional

    • Maximum value of the number (inclusive).

Schema for a JSON null value.

{
  "type": "null"
}

Properties

  • type enum

    • Value: "null"

Schema for a BAQ Tag Link.

{
  "type": "tag_link"
}

Properties

  • type enum

    • Value: "tag_link"
  • enum string[] optional

    • Allowed tag values.
  • min_length int optional

    • Minimum length of the tag (inclusive).
  • max_length int optional

    • Maximum length of the tag (inclusive).
  • sort_property boolean optional

    • Allow sorting of records on this property.

      Default: false

Notes

  • Tags must be between 1 and 100 characters in length.

Schema for a BAQ Blob Link.

{
  "type": "blob_link"
}

Properties

  • type enum

    • Value: "blob_link"
  • max_size int optional

    • Maximum size in bytes of the linked blob.
  • content_types string[] optional

    • Allowed MIME content_type of the linked blob.

Schema for a BAQ Entity Link.

{
  "type": "entity_link"
}

Properties

  • type enum

    • Value: "entity_link"

Schema for a BAQ Record Link.

{
  "type": "record_link"
}

Properties

  • type enum

    • Value: "record_link"
  • record_types RecordLink[] optional

    • Allowed types of the linked record.
  • existential boolean optional

    • Make the record’s existence depend on the linked record.

      Default: false

Schema for a BAQ Version Link.

{
  "type": "version_link"
}

Properties

  • type enum

    • Value: "version_link"
  • record_types RecordLink[] optional

    • Allowed types of the linked record.

Schema for a JSON object with generic properties.

{
  "type": "map",
  "values": {
    "type": "string"
  }
}

Properties

  • type enum

    • Value: "map"
  • values Schema

    • Schema for all the property values in the object.

Union of multiple schemas. Valid if at least one of the sub-schemas is valid.

{
  "type": "union",
  "schemas": [{"type": "string"}, {"type": "int"}]
}

Properties

  • type enum

    • Value: "union"
  • schemas Schema[]

    • Schemas in the union.

      It must contain a minimum of two schemas.

Intersection of multiple schemas. Valid if all sub-schemas are valid.

{
  "type": "intersection",
  "schemas": [
    {
      "type": "object",
      "properties": {"hello": {"type": "string"}}
    },
    {
      "type": "object",
      "properties": {"world": {"type": "string"}}
    }
  ]
}

Properties

  • type enum

    • Value: "intersection"
  • schemas Schema[]

    • Schemas in the intersection.

      It must contain a minimum of two schemas.

Re-use a schema defined in a definitions property somewhere upstream.

{
  "definitions": {
    "name": {"type": "string"}
  },
  "type": "ref",
  "ref": "name"
}

Properties

  • type enum

    • Value: "ref"
  • ref string

    • Name of the schema to use.

      In case of duplicate naming, the schema closest to the ref is used.

      Refs can be recursive.

Schema that always fails validation.

{
  "type": "never"
}

Properties

  • type enum

    • Value: "never"

Define a schema for a user profile object:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "min_length": 1,
      "max_length": 100
    },
    "birth_year": {
      "type": "int",
      "min": 1900
    },
    "favorite_color": {
      "type": "string",
      "enum": ["red", "green", "blue"]
    }
  }
}

Valid JSON:

{
  "name": "Tony Stark",
  "birth_year": 1970,
  "favorite_color": "red"
}

To avoid repeating the same schema again and again, use definitions and ref schemas. A ref schema can point to any upstream definition.

{
  "definitions": {
    "name": {
      "type": "string",
      "min_length": 1,
      "max_length": 100
    }
  },
  "type": "object",
  "properties": {
    "mother_name": {
      "type": "ref",
      "ref": "name"
    },
    "father_name": {
      "type": "ref",
      "ref": "name"
    },
    "sibling_names": {
      "type": "array",
      "items": {"type": "ref", "ref": "name"}
    }
  }
}

Valid JSON:

{
  "mother_name": "Maria",
  "father_name": "Howard",
  "sibling_names": ["Paul", "Henry"]
}

A ref schema can also be used to define a recursive schema. In this example, a user profile can have friends that are each also represented by a user profile (and can have friends of their own, and so on).

{
  "definitions": {
    "profile": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "min_length": 1,
          "max_length": 100
        },
        "friends": {
          "type": "array",
          "items": {
            "type": "ref",
            "ref": "profile"
          }
        }
      }
    }
  },
  "type": "ref",
  "ref": "profile"
}

Valid JSON:

{
  "name": "Maggie",
  "friends": [
    {
      "name": "Sean",
      "friends": []
    },
    {
      "name": "Andersen",
      "friends": [
        {
          "name": "Samantha",
          "friends": []
        }
      ]
    }
  ]
}
© 2024 Quentez