Skip to content

OpenAPI Schemas — Defining Data Models with JSON Schema

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about OpenAPI Schemas. We cover key concepts, practical examples, and best practices to help you master this topic.

OpenAPI schemas define the structure of data exchanged by your API using JSON Schema, specifying types, formats, validation constraints, required fields, nested objects, and array definitions.

In this tutorial, you will learn how to create comprehensive schema definitions that serve as the single source of truth for your API data models, ensuring consistent validation and documentation.

What You'll Learn

You will learn JSON Schema basics, how to define object properties with validation constraints, how to handle nested objects and arrays, how to use enums and oneOf/anyOf, and best practices for schema organization.

Why It Matters

Schemas are the foundation of API documentation. Every request body, response, and parameter references a schema. Well-defined schemas produce clear documentation, enable automatic validation, and generate type-safe client libraries.

Real-World Use

DodaTech maintains a shared schema library that all API services reference. The User schema, Error schema, and Pagination schema are defined once and reused across 20-plus Microservices, ensuring consistent data formats across the entire platform.

flowchart LR
  A[Business Objects] --> B[Schema Definitions]
  B --> C[Request Validation]
  B --> D[Response Serialization]
  B --> E[Client Code Generation]
  B --> F[Documentation]
  B:::current
  classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px

Basic Schema Types

JSON Schema supports primitive types: string, number, integer, boolean, null, array, and object.

components:
  schemas:
    SimpleTypes:
      type: object
      properties:
        name:
          type: string
        age:
          type: integer
        height:
          type: number
        isActive:
          type: boolean
        metadata:
          type: object
          properties:
            createdBy:
              type: string
        tags:
          type: array
          items:
            type: string
        notes:
          type: string
          nullable: true

String Formats

OpenAPI supports standard string formats for validation and documentation.

StringFormats:
  type: object
  properties:
    email:
      type: string
      format: email
      example: user@example.com
    uri:
      type: string
      format: uri
      example: https://api.example.com/users
    uuid:
      type: string
      format: uuid
      example: 550e8400-e29b-41d4-a716-446655440000
    date:
      type: string
      format: date
      example: "2026-06-28"
    dateTime:
      type: string
      format: date-time
      example: "2026-06-28T10:30:00Z"
    password:
      type: string
      format: password
    byte:
      type: string
      format: byte
    binary:
      type: string
      format: binary

Validation Constraints

Restrict values with constraints.

ValidationExample:
  type: object
  properties:
    username:
      type: string
      minLength: 3
      maxLength: 50
      pattern: "^[a-zA-Z0-9_]+$"
      description: Username must be 3-50 alphanumeric characters
    age:
      type: integer
      minimum: 0
      maximum: 150
      exclusiveMinimum: 0
    score:
      type: number
      minimum: 0.0
      maximum: 100.0
      multipleOf: 0.5
    status:
      type: string
      enum: [active, inactive, suspended, deleted]
    email:
      type: string
      format: email
  required:
    - username
    - email

Nested Objects and Arrays

User:
  type: object
  properties:
    id:
      type: integer
      description: Unique identifier
    profile:
      type: object
      properties:
        firstName:
          type: string
        lastName:
          type: string
        avatar:
          type: string
          format: uri
    addresses:
      type: array
      items:
        type: object
        properties:
          street:
            type: string
          city:
            type: string
          zipCode:
            type: string
          isPrimary:
            type: boolean
            default: false
  required:
    - id

Composition with oneOf and anyOf

PaymentMethod:
  type: object
  oneOf:
    - $ref: "#/components/schemas/CreditCard"
    - $ref: "#/components/schemas/PayPal"
    - $ref: "#/components/schemas/CryptoWallet"
  discriminator:
    propertyName: type

CreditCard:
  type: object
  properties:
    type:
      type: string
      enum: [credit_card]
    cardNumber:
      type: string
    expiryDate:
      type: string
      format: date
    cvv:
      type: string

PayPal:
  type: object
  properties:
    type:
      type: string
      enum: [paypal]
    email:
      type: string
      format: email

Schema Reusability Patterns

Define base schemas and extend them:

BaseEntity:
  type: object
  properties:
    id:
      type: integer
    createdAt:
      type: string
      format: date-time
    updatedAt:
      type: string
      format: date-time

User:
  allOf:
    - $ref: "#/components/schemas/BaseEntity"
    - type: object
      properties:
        name:
          type: string
        email:
          type: string
        role:
          type: string
          enum: [admin, member, viewer]

Common Mistakes

  1. Missing required fields — Defining properties but not marking which are required. Clients may send incomplete data and the server receives unexpected null values. Always use the required array.

  2. Overly permissive schemas — Using type: string without format or pattern for structured data like email, dates, or URLs. This bypasses validation and produces unclear docs.

  3. No example values — Omitting the example field on properties. Examples help developers understand what values to send and expect. Always provide realistic examples.

  4. Deeply nested schemas — Creating objects nested five-plus levels deep. This makes documentation hard to read and schemas hard to reuse. Flatten where possible.

  5. Inconsistent naming conventions — Using snake_case in some schemas and camelCase in others. Pick one convention and use it everywhere.

Practice Questions

  1. What JSON Schema types are supported in OpenAPI?
  2. How do you define a string field that must be a valid email?
  3. What is the difference between oneOf and anyOf?
  4. How do you mark certain fields as required in a schema?
  5. What validation constraints can you apply to numeric fields?

Challenge

Design a complete schema set for an e-commerce API. Define schemas for Product (with categories, variants, pricing), Order (with line items, shipping address, payment info), Customer (with addresses, preferences), and common response schemas for pagination and errors.

FAQ

Can I define the same field in multiple schemas?

Yes, but it is better to define it once in a reusable component and reference it. For example, define Address once and reference it in User, Order, and Shipping schemas.

How do I handle null values in OpenAPI?

Use nullable: true on the property. In OpenAPI 3.0, use type: string, nullable: true. In OpenAPI 3.1 with full JSON Schema, use type: ["string", "null"].

What is the difference between allOf and $ref?

$ref includes all properties from the referenced schema. allOf combines multiple schemas, potentially adding or overriding properties. allOf is useful for composing schemas from multiple sources.

Can schemas validate business rules like start_date before end_date?

JSON Schema has limited cross-field validation. For complex business rules, validate in your application code. Document the rules in the schema description.

How detailed should schema descriptions be?

Detailed enough for a developer to understand the field without guessing. Include the purpose, valid values, format, and an example. Keep descriptions concise but complete.

Mini Project

Create a schema library for a blog API. Define schemas for Article (title, content, author, tags, publishDate, status), Author (name, bio, avatar, socialLinks), Comment (content, author, createdAt), and Category (name, slug, description). Include appropriate validation constraints, examples, and required fields.

What's Next

In the next lesson, you will learn how to define parameters for API endpoints, including path, query, header, and cookie parameters with validation and documentation.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro