Small FSharp based DSL for writing json.
object
CE is for creating json objects.
array
CE is for creating json arrays.
property
operation is for creating properties. Properties can be Json element, primitives, or DateTime.
object{
property "name" "John"
property "age" 30
property "married" true
property "birthday" (System.DateTime.Now)
property "children" (array{
"Jane"
"Mark"
})
property "Job" (object {
property "title" "Developer"
property "company" "a company"
})
}
You can mark properties as required by using the +.
operator. The json creation will fail when the expression creating the property returns None
:
object {property "i am required" (+. (Option.None))} // System.Exception: Could not create Json Object, as required elements were missing: Value was missing
object {property "i am required" (+. Option.Some 3))} // val it: Nodes.JsonObject = seq [[hi, 3] {Key = "hi"; Value = 3;}]
Vice versa, mark properties as optional by using the -.
operator. The property will be in the resulting json object when the expression creating the property returns Some value
, and be ommitted when it returns None
:
object {property "i am optional" (-. (Option.None))} // val it: Nodes.JsonObject = seq []
object {property "i am optional" (-. Option.Some 3))} // val it: Nodes.JsonObject = seq [[hi, 3] {Key = "hi"; Value = 3;}]
You can either use the +.
and -.
operators in combination with the object creation CE by wrapping the result in an Option
:
object {property "innerObject" (-. Option.None))}
object {property "i am optional" (+. Option.Some (object { property "inner" "yes"})))}
or you can use the required
and optional
Custom Operations:
The main reason we provide the required/optional logic is to facilitate conversion between formats.
As an example, lets define a type Person
, which has a name and an optional Email address:
type Person = {
Name: string
Email: string option
}
While in our source format, the email is optional, we want to convert it to a format where the email is required.
We can convert the Person
type to a json object with the email when it is present, and fail otherwise:
let convertRequired (p:Person) =
object {
property "name" p.Name
property "email" (+. p.Email)
}
convert {Name = "Duderich"; Email = Option.None} // System.Exception: Could not create Json Object, as required elements were missing: Value was missing
convert {Name = "Duderich"; Email = Option.Some "yes@yes.yup"} //val it: Nodes.JsonObject =seq[[name, Duderich] {Key = "name";Value = Duderich;}; [email, yes@yes.yup] {Key = "email"; Value = yes@yes.yup;}]
or we can convert the Person
type to a json object without the email when it is not present, and include it when it is present:
let convertOptional (p:Person) =
object {
property "name" p.Name
property "email" (-. p.Email)
}
convertOptional {Name = "Duderich"; Email = Option.None} //val it: Nodes.JsonObject = seq [[name, Duderich] {Key = "name"; Value = Duderich;}]
convertOptional {Name = "Duderich"; Email = Option.Some "yes@yes.yup"} //val it: Nodes.JsonObject =seq[[name, Duderich] {Key = "name";Value = Duderich;}; [email, yes@yes.yup] {Key = "email"; Value = yes@yes.yup;}]