KaaIoT, MikroTik & Teltonika Webinar. Build and Upgrade Equipment with IoT for Remote Access & Control
Kaa Documentation

JSON Schema Guide

JSON Schema Guide

This guide explains how JSON Schema is used within our form system, based on react-jsonschema-form v1.6 and the JSON Schema specification. JSON Schema defines the expected data structure, types, and validation rules for the form data.

Basic Structure

A typical JSON schema defines an object with properties corresponding to form fields.

{
  "type": "object",
  "properties": {
    "fieldName": {
      "type": "string",
      "title": "User-Friendly Field Name",
      "description": "Help text for the user."
    },
    "anotherField": {
      "type": "number",
      "title": "Another Field"
    }
  }
}

Common Keywords Used

We utilize several standard JSON Schema keywords:

  • type: Specifies the data type for a field (string, number, integer, boolean, array, object).
  • title: A user-friendly label displayed for the field.
    • Note: Values provided here are treated as translation keys (e.g., "title": "common.fieldLabel") and are automatically looked up in the internationalization files.
  • description: Help text or hints displayed to the user, often as a tooltip or subtitle.
  • properties: Defines the fields within an object type schema.
  • required: An array of strings listing the property names (within the current object) that must have a value.
  • enum: An array of predefined allowed values for a field. Often used for dropdowns or radio buttons.
  • enumNames: An array of user-friendly labels corresponding to the values in the enum array. If omitted, the enum values themselves are displayed.
    • Note: Similar to title, values in this array are treated as translation keys.
  • default: A default value to pre-populate the field with.
  • items: Defines the schema for elements within an array type field. Can be a single schema (for uniform arrays) or an array of schemas (for tuple-like arrays).
  • minItems: Minimum number of items required in an array.
  • format: Provides semantic meaning to string types (e.g., date-time, email, uri, json). In our case, json is used with the JsonEditor widget.
  • dependencies: Defines conditional logic where the presence or value of one field affects the requirements or schema of others.
  • oneOf: Used within dependencies, this allows specifying different schema variations based on the value of a controlling field.

Example: Service Integration (EPList Widget)

This example shows several keywords in action:

{
  "type": "object",
  "title": "Data source",
  "properties": {
    "service": {
      "type": "string",
      "title": "Metadata service instance name",
      "description": "form.hints.eprServiceInstance"
    },
    "applicationSelection": {
      "type": "string",
      "title": "Show endpoints from",
      "enum": ["Single", "Multi"], // Allowed internal values
      "enumNames": ["Single application", "Multiple applications"], // Displayed labels
      "default": "Single"
    },
    // ... other properties
  },
  "required": ["service"], // 'service' must be provided
  "dependencies": {
    "applicationSelection": { // Logic depends on 'applicationSelection'
      "oneOf": [
        { // Schema variation when applicationSelection is 'Single'
          "properties": {
            "applicationSelection": { "enum": ["Single"] },
            "applicationName": {
              "type": "string",
              "title": "Application",
              "description": "Only display endpoints that belong to this application",
              "enum": ["__IGNORE_VALUE__"], // Initial/placeholder enum
              "enumNames": ["All"]
            },
            // ... more single-application specific fields
          }
        },
        { // Schema variation when applicationSelection is 'Multi'
          "properties": {
            "applicationSelection": { "enum": ["Multi"] },
            "applications": {
              "type": "string", // Often used with multi-select widget
              "title": "Application",
              "description": "Only display endpoints that belong to applications"
            }
          }
        }
      ]
    }
  }
}
  • Note how enum and enumNames provide choices for applicationSelection.
  • required makes the service field mandatory.
  • dependencies combined with oneOf changes the available fields (applicationName vs. applications) based on the applicationSelection value. The empty enum for applicationName is typical; it gets populated dynamically by UI Schema transformations (covered in a separate guide).

Example: Array Items (EPList Widget Columns)

{
  "columns": {
    "type": "array",
    "title": "Columns",
    "minItems": 1, // At least one column is required
    "items": { // Defines the schema for each object in the 'columns' array
      "type": "object",
      "properties": {
        "display": {
          "type": "string",
          "title": "Column title"
        },
        "cellType": {
          "type": "string",
          "title": "Cell type",
          "enum": ["text", "icon", "action", /* ... */],
          "default": "text"
        },
        // ... other column properties
      },
      "required": ["display"] // Each column must have a title
    }
  }
}

This defines an array named columns, where each element must be an object conforming to the items schema, requiring at least a display property.

For more advanced schema design, refer to the JSON Schema specification and the base library documentation. The real power comes from combining this schema definition with the UI Schema and Transformations, covered in their respective guides.