ACPex.Schema.Codec (ACPex v0.1.1)

Copy Markdown View Source

Encoding and decoding utilities for ACP schemas.

This module provides functions to convert between Ecto schemas and JSON, automatically handling the camelCase ↔ snake_case conversion via the :source field option defined in each schema.

Features

  • Encoding: Converts Ecto schemas to JSON strings with camelCase keys
  • Decoding: Converts JSON strings to Ecto schemas with snake_case fields
  • Automatic case conversion via :source field mappings
  • Nil values are automatically omitted from encoded output
  • Proper error handling and validation

Examples

# Encoding
request = %ACPex.Schema.Connection.InitializeRequest{
  protocol_version: 1,
  capabilities: %{}
}
ACPex.Schema.Codec.encode!(request)
#=> ~s({"protocolVersion":1,"capabilities":{}})

# Decoding
json = ~s({"protocolVersion":1,"capabilities":{}})
ACPex.Schema.Codec.decode!(json, ACPex.Schema.Connection.InitializeRequest)
#=> %ACPex.Schema.Connection.InitializeRequest{protocol_version: 1, capabilities: %{}}

Design Philosophy

This module eliminates the need for manual case conversion by leveraging Ecto's built-in support for field name mapping via the :source option. Each schema defines its own mappings, making them self-documenting and serving as the single source of truth for the protocol specification.

Summary

Functions

Decodes a JSON string into an Ecto schema struct.

Decodes a JSON string into an Ecto schema struct.

Decodes a map with camelCase keys into an Ecto schema struct.

Decodes a map with camelCase keys into an Ecto schema struct.

Encodes an Ecto schema struct to a JSON string.

Encodes an Ecto schema struct to a map with camelCase keys.

Functions

decode(json, schema_module)

@spec decode(String.t(), module()) :: {:ok, struct()} | {:error, term()}

Decodes a JSON string into an Ecto schema struct.

Uses Jason.decode/1 to parse the JSON, then Ecto.embedded_load/3 to convert the camelCase keys to snake_case fields according to the schema's :source field mappings.

Parameters

  • json - JSON string to decode
  • schema_module - The Ecto schema module to decode into

Returns

{:ok, struct} on success, or {:error, reason} on failure.

Examples

iex> json = ~s({"protocolVersion":1,"capabilities":{}})
iex> ACPex.Schema.Codec.decode(json, InitializeRequest)
{:ok, %InitializeRequest{protocol_version: 1, capabilities: %{}}}

decode!(json, schema_module)

@spec decode!(String.t(), module()) :: struct()

Decodes a JSON string into an Ecto schema struct.

Same as decode/2 but raises on error.

Parameters

  • json - JSON string to decode
  • schema_module - The Ecto schema module to decode into

Returns

An Ecto schema struct.

Examples

iex> json = ~s({"protocolVersion":1,"capabilities":{}})
iex> ACPex.Schema.Codec.decode!(json, InitializeRequest)
%InitializeRequest{protocol_version: 1, capabilities: %{}}

decode_from_map(data, schema_module)

@spec decode_from_map(map(), module()) :: {:ok, struct()} | {:error, term()}

Decodes a map with camelCase keys into an Ecto schema struct.

Uses Ecto.embedded_load/3 to convert the map to a struct, respecting the schema's :source field mappings.

Parameters

  • data - Map with camelCase string keys
  • schema_module - The Ecto schema module to decode into

Returns

{:ok, struct} on success, or {:error, reason} on failure.

Examples

iex> data = %{"protocolVersion" => 1, "capabilities" => %{}}
iex> ACPex.Schema.Codec.decode_from_map(data, InitializeRequest)
{:ok, %InitializeRequest{protocol_version: 1, capabilities: %{}}}

decode_from_map!(data, schema_module)

@spec decode_from_map!(map(), module()) :: struct()

Decodes a map with camelCase keys into an Ecto schema struct.

Same as decode_from_map/2 but raises on error.

Parameters

  • data - Map with camelCase string keys
  • schema_module - The Ecto schema module to decode into

Returns

An Ecto schema struct.

Examples

iex> data = %{"protocolVersion" => 1, "capabilities" => %{}}
iex> ACPex.Schema.Codec.decode_from_map!(data, InitializeRequest)
%InitializeRequest{protocol_version: 1, capabilities: %{}}

encode!(struct)

@spec encode!(struct()) :: String.t()

Encodes an Ecto schema struct to a JSON string.

Uses Ecto.embedded_dump/2 to convert the struct to a map with camelCase keys (respecting :source field mappings), then encodes to JSON.

Parameters

  • struct - An Ecto schema struct to encode

Returns

A JSON string representation of the struct with camelCase keys.

Examples

iex> request = %InitializeRequest{protocol_version: 1, capabilities: %{}}
iex> ACPex.Schema.Codec.encode!(request)
~s({"protocolVersion":1,"capabilities":{}})

encode_to_map!(struct)

@spec encode_to_map!(struct()) :: map()

Encodes an Ecto schema struct to a map with camelCase keys.

Similar to encode!/1 but returns a map instead of a JSON string. Useful for composing nested structures.

Parameters

  • struct - An Ecto schema struct to encode

Returns

A map with camelCase keys.

Examples

iex> request = %InitializeRequest{protocol_version: 1, capabilities: %{}}
iex> ACPex.Schema.Codec.encode_to_map!(request)
%{"protocolVersion" => 1, "capabilities" => %{}}