Repository F# setup
open Reified
open Reified.Refinements
open Reified.Result
open Reified.Schema.JsonNested Models And Collections Tutorial
This tutorial parses an order that contains a nested address and a collection of line items. Address and Item
own their canonical schemas, so Order can infer both the nested field and the list item schema.
Declare The Schemas
open Reified
open Reified.SchemaDSL
type Address =
{ Street: string; City: string }
static member Schema(_: Address) : Schema<Address> =
schema<Address> {
field _.Street
field _.City
construct (fun street city -> { Street = street; City = city })
}
type Item =
{ Sku: string; Quantity: int }
static member Schema(_: Item) : Schema<Item> =
schema<Item> {
field _.Sku
field _.Quantity {
constrain (greaterThan 0)
}
construct (fun sku quantity -> { Sku = sku; Quantity = quantity })
}
type Order =
{ Address: Address
Items: Item list }
let orderSchema =
schema<Order> {
field _.Address
field _.Items {
constrain (minLength 1)
}
construct (fun address items -> { Address = address; Items = items })
}Adapt Nested Input
Configuration-style keys carry nesting with : separators and numeric collection indexes; JSON-like input nests
naturally. Both produce the same shape:
let raw =
Data.ofConfiguration
[ "address:street", "12 Analytical Way"
"address:city", "London"
"items:0:sku", "SKU-1"
"items:0:quantity", "2"
"items:1:sku", "SKU-2"
"items:1:quantity", "0" ]Parse And Read Item Errors
Every item is parsed and every item error is kept — one bad line item does not hide the others:
let parsed = Schema.parseRetainingInput orderSchema raw
parsed.ErrorsFor "items[1].quantity" // quantity 0 fails greaterThan 0
parsed.ErrorsFor "items[0].sku" // [] — the first item is fineNested diagnostics are prefixed with the field name (address.city), collection diagnostics with the item index
(items[1].quantity), and the raw values redisplay by the same paths:
Data.redisplayPath "items[1].quantity" parsed.Input // "0"Count Constraints
Collection constraints (minLength, maxLength, count, distinct) attach to the collection field itself and report
on the collection path (items), separately from per-item errors.
Use a field block with withSchema when a nested field needs a schema local to its parent, when wrapping a third-party
type, or for recursive composition with Schema.defer.
Next
- Input Sources for the full adapter catalog.