Alpha Version: You are viewing the ALPHA documentation. This is an experimental version and may contain breaking changes.
Skip to main content

Serialization

Sury

Sury is the serialization library used by Reventless for JSON encoding and decoding using a PPX.

Basic Usage

@schema annotation

The library automatically generates schema functions for annotated types. The framework relies on these schemas and uses them internally for serialization and deserialization.

Basic Types

@schema
type userId = string

@schema
type count = int

Records

@schema
type countsState = {
id: string,
count: int,
}

@schema
type referencesState = {
id: string,
inc: int,
}

Common Patterns

Variants

Simple variants for enums:

@schema
type effect = Allow | Deny

Complex variants with data:

@schema
type command =
| Heartbeat
| Connect(pluginDefinition)
| Disconnect
| Activate
| Deactivate

@schema
type event =
| UnknownPluginDetected
| Connected(pluginDefinition)
| Disconnected(pluginDefinition)
| Activated(pluginDefinition)
| Deactivated(pluginDefinition)

Key Annotations

Custom JSON field names with @as

@schema
type principal = {
@as("AWS") aws?: string,
@as("Service") service?: string,
}

Unboxed variants with @unboxed

@schema @unboxed
type actions = | @as("*") AllActions | Action(string)

Framework Integration

Framework Internal

This section describes how Reventless uses Sury schemas internally. Most developers won't need to use these functions directly.

Generated Schema Functions

For each @schema annotated type, Sury generates:

  • A schema object (e.g., countsStateSchema)
  • Encoding/decoding functions accessible through Message.encode and Message.decode

Serialization Usage

The framework uses these patterns for serialization:

// Encoding data to JSON
let json = state->Message.encode(countsStateSchema)

// Decoding JSON to typed data
switch jsonData->Message.decode(countsStateSchema) {
| {id, count} => // Handle decoded data
| exception _ => // Handle decode errors
}

Practical Example

From the Counter component:

@schema
type countsState = {
id: string,
count: int,
}

// Usage in callback handler
counts->Array.filterMap(state =>
switch state->Message.decode(countsStateSchema) {
| {id, count} if count == 0 =>
// Process completed counter
Some(processCounterEvent(id, count))
| {id, count} =>
// Log current state
Js.log(`Counter ${id} at ${count->Int.toString}`)
None
| exception _ =>
Js.log("Failed to decode counter state")
None
}
)
warning

Any type referenced from inside an annotated type needs to either be a built-in type or another annotated type. The compiler will error otherwise.