Skip to content

Instantly share code, notes, and snippets.

@mausch
Created April 14, 2014 04:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mausch/10616448 to your computer and use it in GitHub Desktop.
Save mausch/10616448 to your computer and use it in GitHub Desktop.
type Address = {
Name: string
Address1: string option
Address2: string option
Code: string option
City: string option
Country: string option
}
type Client = {
Name: string
Address: Address option
Email: string option
}
type InvoiceRow = {
Title: string
Quantity: int option
QuantityUnit: string option
Price: decimal option
Tax: decimal option
TaxPrice: decimal option
TotalTaxPrice: decimal option
TotalPrice: decimal option
}
type Invoice = {
Title: string
Client: Client option
Address: Address option
InvoiceRows: InvoiceRow list
}
open System
open Fleece // https://www.nuget.org/packages/Fleece/
open Fleece.Operators
open FSharpPlus
type Address with
static member FromJSON (_: Address) =
function
| JObject o ->
monad {
let! name = o .@ "name"
let! address1 = o .@? "address_1"
let! address2 = o .@? "address_2"
let! code = o .@? "code"
let! city = o .@? "city"
let! country = o .@? "country"
return {
Address.Name = name
Address1 = address1
Address2 = address2
Code = code
City = city
Country = country
}
}
| x -> Failure (sprintf "Expected JSON object for Address, found %A" x)
let email address =
try
System.Net.Mail.MailAddress address |> ignore
Success address
with _ -> Failure (sprintf "Invalid email address '%s'" address)
let optValidate (f: 'a -> Choice<'a, _>) =
function
| None -> Success None
| Some v -> f v |> map Some
type Client with
static member FromJSON (_: Client) =
function
| JObject o ->
monad {
let! name = o .@ "name"
let! address = o .@? "address"
let! email = o .@? "email" >>= optValidate email
return {
Client.Name = name
Address = address
Email = email
}
}
| x -> Failure (sprintf "Expected JSON object for Client, found %A" x)
let min minimumValue value =
if value >= minimumValue
then Success value
else Failure (sprintf "Expected minimum value %A, found %A" minimumValue value)
type InvoiceRow with
static member FromJSON (_: InvoiceRow) =
function
| JObject o ->
monad {
let! title = o .@ "title"
let! quantity = o .@? "quantity" >>= optValidate (min 0)
let! quantityUnit = o .@? "quantityUnit"
let! price = o .@? "price"
let! tax = o .@? "tax" >>= optValidate (min 0m)
let! taxPrice = o .@? "taxPrice" >>= optValidate (min 0m)
let! totalTaxPrice = o .@? "totalTaxPrice"
let! totalPrice = o .@? "totalPrice"
return {
InvoiceRow.Title = title
Quantity = quantity
QuantityUnit = quantityUnit
Price = price
Tax = tax
TaxPrice = taxPrice
TotalTaxPrice = totalTaxPrice
TotalPrice = totalPrice
}
}
| x -> Failure (sprintf "Expected JSON object for InvoiceRow, found %A" x)
// dummy implementation
let foreignKeyInCollection table key = Success { Client.Name = "John Doe"; Address = None; Email = None }
type Invoice with
static member FromJSON (_: Invoice) =
function
| JObject o ->
monad {
let! title = o .@ "title"
let! client = o .@? "client" >>= optValidate (foreignKeyInCollection "client")
let! address = o .@? "address"
let! invoiceRows = o .@? "invoiceRows" |> map (fun l -> defaultArg l [])
return {
Invoice.Title = title
Client = client
Address = address
InvoiceRows = invoiceRows
}
}
| x -> Failure (sprintf "Expected JSON object for Invoice, found %A" x)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment