> For the complete documentation index, see [llms.txt](https://crystal-garage.gitbook.io/lustra-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://crystal-garage.gitbook.io/lustra-docs/model/column-types/converters.md).

# Converters

Converters translate values between PostgreSQL/Crystal DB values and model column types.

Lustra registers converters for common built-in types. Custom types need a converter registered with `Lustra::Model::Converter.add_converter`.

## Declare a Converter

A converter must provide:

```crystal
def self.to_column(value)
end

def self.to_db(value)
end
```

Example:

```crystal
struct MyApp::Color
  property r : UInt8 = 0
  property g : UInt8 = 0
  property b : UInt8 = 0
  property a : UInt8 = 255

  def self.from_string(value : String)
    # parse a database value
  end

  def to_s
    # serialize to a database value
  end
end

class MyApp::ColorConverter
  def self.to_column(value) : MyApp::Color?
    case value
    when Nil
      nil
    when MyApp::Color
      value
    else
      MyApp::Color.from_string(value.to_s)
    end
  end

  def self.to_db(value : MyApp::Color?)
    value.try(&.to_s)
  end
end

Lustra::Model::Converter.add_converter("MyApp::Color", MyApp::ColorConverter)
```

Then use the type in a model:

```crystal
class MyApp::Paint
  include Lustra::Model

  column id : Int64, primary: true, presence: false
  column color : MyApp::Color
end
```

When no `converter` option is given, Lustra looks up a converter from the Crystal type name.

## `converter` Option

Use the `converter` option when the converter name should not be inferred from the column type:

```crystal
Lustra::Model::Converter.add_converter("color_from_hex", MyApp::ColorConverter)

class MyApp::Paint
  include Lustra::Model

  column id : Int64, primary: true, presence: false
  column color : MyApp::Color, converter: "color_from_hex"
end
```

Converter lookup happens at compile time. If a converter is missing, Lustra raises a compile-time error explaining that no converter was found for the requested type/name.

## JSON Serializable Converter

For JSON serializable types, Lustra can generate a converter:

```crystal
class Actor
  include JSON::Serializable

  property name : String
end

Lustra.json_serializable_converter(Actor)

class Movie
  include Lustra::Model

  column id : Int64, primary: true, presence: false
  column actor : Actor
end
```

The generated converter stores the value as JSON and rebuilds the Crystal object when reading from the database.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://crystal-garage.gitbook.io/lustra-docs/model/column-types/converters.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
