Zodra

Response Format

Zodra's response envelope and serialization conventions

Response Format

All Zodra responses follow a consistent envelope structure.

Single object

zodra_respond(product)
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Widget",
    "price": 9.99,
    "published": true,
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z"
  }
}

Collection

zodra_respond_collection(products, meta: { total: 42 })
{
  "data": [
    { "id": "...", "name": "Widget", "price": 9.99 },
    { "id": "...", "name": "Gadget", "price": 19.99 }
  ],
  "meta": {
    "total": 42
  }
}

Validation errors

Returned automatically when zodra_params fails validation:

{
  "errors": {
    "name": ["must be at least 1 character"],
    "price": ["must be greater than or equal to 0"]
  }
}

HTTP status: 422 Unprocessable Entity.

Business errors

Returned by zodra_rescue when a mapped exception is raised:

{
  "error": {
    "code": "invalid_transition",
    "message": "Order cannot be confirmed in its current state"
  }
}

HTTP status: defined in the contract error declaration.

Serialization

Response objects are serialized based on the action's response definition in the contract:

  • Only fields defined in the response type are included
  • Key format follows the key_format configuration (default: camelCase)
  • Nested references and arrays are serialized recursively
  • Fields not present on the object are omitted

This means the contract's response definition acts as a whitelist — no accidental data leaks.

Context

Pass a context hash to ResponseSerializer — it propagates recursively through nested references and arrays:

ResponseSerializer.call(object, definition, context: { ability: current_ability })

Attribute blocks with two parameters receive this context:

Zodra.type :item do
  boolean :can_edit do |item, context|
    context[:ability].can?(:edit, item)
  end
end

See Attribute blocks for full details.

Strict serialization

When strict_serialization is enabled (default in development/test), Zodra raises MissingAttributeError if a required attribute cannot be found on the serialized object.

The error message includes:

  • Full dotted path through nested references (orders[0].customer.email)
  • Similar key suggestions using fuzzy matching
  • Hints when a camelCase key exists but snake_case was expected
Zodra::MissingAttributeError: attribute :access_token not found in :page_props

  Expected key:    :access_token (string)
  Similar key:     :access_tokens   ← did you mean this?
  Path:            accessToken
  Object class:    Hash
  Available keys (5): :access_tokens, :sse_url, :venues, :settings, :permissions

In production, this logs a warning instead of raising. Configure via strict_serialization — see Configuration.

On this page