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.