F# library supporting Dynamic Objects including inheritance in functional style.
DynamicObj
builds on ´System.Dynamic´ but adds object inheritance.
One main use case of this library is the dynamic generation of JSON objects - especially nested objects with optional properties - aimed to be used from javascript wuith the init/style pattern:
Use it for your custom types via inheritance:
#r "nuget: Newtonsoft.JSON, 13.0.1"
open Newtonsoft.Json
open DynamicObj
type A() =
inherit DynamicObj()
static member init
(
?SomeProp: int
) =
A()
|> A.style
(
?SomeProp = SomeProp
)
static member style
(
?SomeProp: int
) =
fun (a:A) ->
SomeProp |> DynObj.setValueOpt a "some_prop"
a
You can use the DynObj.print
function to look at the dynamic members of the object:
let aformat = A.init(42) |> DynObj.format
And this is how the serialized JSON looks like:
let aSerialized =
A.init(42)
|> JsonConvert.SerializeObject
type MyComplexJSONType() =
inherit DynamicObj()
static member init
(
?PropA: int [],
?PropB: A
) =
MyComplexJSONType()
|> MyComplexJSONType.style
(
?PropA = PropA,
?PropB = PropB
)
static member style
(
?PropA: int [],
?PropB: A
) =
fun (t:MyComplexJSONType) ->
PropA |> DynObj.setValueOpt t "prop_a"
PropB |> DynObj.setValueOpt t "prop_b"
t
let complex =
MyComplexJSONType.init(
PropA = [|42;1337|],
PropB = A.init(68) // nested dynamic objects
)
let complexSerialized =
complex
|> JsonConvert.SerializeObject
You can use the DynObj.print
function to look at the dynamic members of the object:
complex |> DynObj.print
?prop_a: System.Int32[]
?prop_b:
?some_prop: 68
|
And this is how the serialized JSON looks like:
"{"prop_a":[42,1337],"prop_b":{"some_prop":68}}"
|
#r "nuget: Newtonsoft.JSON, 12.0.3"
open Newtonsoft.Json
open DynamicObj
type ImmutableA() =
inherit ImmutableDynamicObj()
static member init
(
?SomeProp: int
) =
ImmutableA()
|> ImmutableA.style
(
?SomeProp = SomeProp
)
static member style
(
?SomeProp: int
) =
fun (a:ImmutableA) ->
a
|> ImmutableDynamicObj.addOpt "some_prop" SomeProp
You can use the ImmutableDynamicObj.print
function to look at the dynamic members of the object:
ImmutableA.init(42) |> ImmutableDynamicObj.print
And this is how the serialized JSON looks like:
let immutableASerialized =
ImmutableA.init(42)
|> JsonConvert.SerializeObject
DynamicObj.Operators
adds usefull operators for adding properties:
open DynamicObj.Operators
type ImmutableMyComplexJSONType() =
inherit ImmutableDynamicObj()
static member init
(
?PropA: int [],
?PropB: A
) =
ImmutableMyComplexJSONType()
|> ImmutableMyComplexJSONType.style
(
?PropA = PropA,
?PropB = PropB
)
static member style
(
?PropA: int [],
?PropB: A
) =
fun (t:ImmutableMyComplexJSONType) ->
t
++? ("prop_a", PropA)
++? ("prop_b", PropB)
let immutableComplex =
ImmutableMyComplexJSONType.init(
PropA = [|42;1337|],
PropB = A.init(68) // nested dynamic objects
)
let immutableComplexSerialized =
immutableComplex
|> JsonConvert.SerializeObject
You can use the DynObj.print
function to look at the dynamic members of the object:
complex |> DynObj.print
?prop_a: System.Int32[]
?prop_b:
?some_prop: 68
|
And this is how the serialized JSON looks like:
"{"prop_a":[42,1337],"prop_b":{"some_prop":68}}"
|
namespace Newtonsoft
namespace Newtonsoft.Json
namespace DynamicObj
type A =
inherit DynamicObj
new: unit -> A
static member init: ?SomeProp: int -> A
static member style: ?SomeProp: int -> (A -> A)
Multiple items
namespace DynamicObj
--------------------
type DynamicObj =
inherit DynamicObject
new: unit -> DynamicObj
member CopyDynamicProperties: unit -> DynamicObj
member CopyDynamicPropertiesTo: target: DynamicObj -> unit
override Equals: o: obj -> bool
override GetDynamicMemberNames: unit -> IEnumerable<string>
override GetHashCode: unit -> int
member GetProperties: includeInstanceProperties: bool -> seq<KeyValuePair<string,obj>>
member Remove: name: string -> bool + 1 overload
member SetValue: name: string * value: 'a -> unit
...
--------------------
new: unit -> DynamicObj
val SomeProp: int option
Multiple items
val int: value: 'T -> int (requires member op_Explicit)
<summary>Converts the argument to signed 32-bit integer. This is a direct conversion for all
primitive numeric types. For strings, the input is converted using <c>Int32.Parse()</c>
with InvariantCulture settings. Otherwise the operation requires an appropriate
static conversion method on the input type.</summary>
<param name="value">The input value.</param>
<returns>The converted int</returns>
<example id="int-example"><code lang="fsharp"></code></example>
--------------------
[<Struct>]
type int = int32
<summary>An abbreviation for the CLI type <see cref="T:System.Int32" />.</summary>
<category>Basic Types</category>
--------------------
type int<'Measure> =
int
<summary>The type of 32-bit signed integer numbers, annotated with a unit of measure. The unit
of measure is erased in compiled code and when values of this type
are analyzed using reflection. The type is representationally equivalent to
<see cref="T:System.Int32" />.</summary>
<category>Basic Types with Units of Measure</category>
new: unit -> A
static member A.style: ?SomeProp: int -> (A -> A)
val a: A
module DynObj
from DynamicObj
val setValueOpt: dyn: DynamicObj -> propName: string -> _arg1: 'a option -> unit
val aformat: string
static member A.init: ?SomeProp: int -> A
val format: d: DynamicObj -> string
val aSerialized: string
type JsonConvert =
static member DeserializeAnonymousType<'T> : value: string * anonymousTypeObject: 'T -> 'T + 1 overload
static member DeserializeObject: value: string -> obj + 7 overloads
static member DeserializeXNode: value: string -> XDocument + 3 overloads
static member DeserializeXmlNode: value: string -> XmlDocument + 3 overloads
static member PopulateObject: value: string * target: obj -> unit + 1 overload
static member SerializeObject: value: obj -> string + 7 overloads
static member SerializeXNode: node: XObject -> string + 2 overloads
static member SerializeXmlNode: node: XmlNode -> string + 2 overloads
static member ToString: value: DateTime -> string + 24 overloads
static val False: string
...
<summary>
Provides methods for converting between .NET types and JSON types.
</summary>
<example><code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="SerializeObject" title="Serializing and Deserializing JSON with JsonConvert" /></example>
JsonConvert.SerializeObject(value: obj) : string
JsonConvert.SerializeObject(value: obj, settings: JsonSerializerSettings) : string
JsonConvert.SerializeObject(value: obj, [<System.ParamArray>] converters: JsonConverter[]) : string
JsonConvert.SerializeObject(value: obj, formatting: Formatting) : string
JsonConvert.SerializeObject(value: obj, formatting: Formatting, settings: JsonSerializerSettings) : string
JsonConvert.SerializeObject(value: obj, ``type`` : System.Type, settings: JsonSerializerSettings) : string
JsonConvert.SerializeObject(value: obj, formatting: Formatting, [<System.ParamArray>] converters: JsonConverter[]) : string
JsonConvert.SerializeObject(value: obj, ``type`` : System.Type, formatting: Formatting, settings: JsonSerializerSettings) : string
Multiple items
type MyComplexJSONType =
inherit DynamicObj
new: unit -> MyComplexJSONType
static member init: ?PropA: int[] * ?PropB: A -> MyComplexJSONType
static member style: ?PropA: int[] * ?PropB: A -> (MyComplexJSONType -> MyComplexJSONType)
--------------------
new: unit -> MyComplexJSONType
val PropA: int[] option
val PropB: A option
static member MyComplexJSONType.style: ?PropA: int[] * ?PropB: A -> (MyComplexJSONType -> MyComplexJSONType)
val t: MyComplexJSONType
val complex: MyComplexJSONType
static member MyComplexJSONType.init: ?PropA: int[] * ?PropB: A -> MyComplexJSONType
val complexSerialized: string
val print: d: DynamicObj -> unit
Multiple items
type ImmutableA =
inherit ImmutableDynamicObj
new: unit -> ImmutableA
static member init: ?SomeProp: int -> ImmutableA
static member style: ?SomeProp: int -> (ImmutableA -> ImmutableA)
--------------------
new: unit -> ImmutableA
Multiple items
type ImmutableDynamicObj =
new: unit -> ImmutableDynamicObj
override Equals: o: obj -> bool
override GetHashCode: unit -> int
member TryGetTypedValue: name: string -> 'a option
member TryGetValue: name: string -> obj option
static member add: name: string -> newValue: obj -> object: 'c -> 'c (requires 'c :> ImmutableDynamicObj and default constructor)
static member addOpt: name: string -> newValue: 'c option -> object: 'd -> 'd (requires 'd :> ImmutableDynamicObj and default constructor)
static member addOptBy: name: string -> newValue: 'd option -> f: ('d -> 'e) -> object: 'f -> 'f (requires 'f :> ImmutableDynamicObj and default constructor)
static member combineWith: sourceObject: #ImmutableDynamicObj -> targetObject: 'a1 -> 'a1 (requires 'a1 :> ImmutableDynamicObj and default constructor)
static member format: object: #ImmutableDynamicObj -> string
...
<summary>
Represents an DynamicObj's counterpart
with immutability enabled only.
</summary>
--------------------
new: unit -> ImmutableDynamicObj
static member ImmutableA.style: ?SomeProp: int -> (ImmutableA -> ImmutableA)
val a: ImmutableA
static member ImmutableDynamicObj.addOpt: name: string -> newValue: 'c option -> object: 'd -> 'd (requires 'd :> ImmutableDynamicObj and default constructor)
static member ImmutableA.init: ?SomeProp: int -> ImmutableA
static member ImmutableDynamicObj.print: object: #ImmutableDynamicObj -> unit
val immutableASerialized: string
module Operators
from DynamicObj
Multiple items
type ImmutableMyComplexJSONType =
inherit ImmutableDynamicObj
new: unit -> ImmutableMyComplexJSONType
static member init: ?PropA: int[] * ?PropB: A -> ImmutableMyComplexJSONType
static member style: ?PropA: int[] * ?PropB: A -> (ImmutableMyComplexJSONType -> ImmutableMyComplexJSONType)
--------------------
new: unit -> ImmutableMyComplexJSONType
static member ImmutableMyComplexJSONType.style: ?PropA: int[] * ?PropB: A -> (ImmutableMyComplexJSONType -> ImmutableMyComplexJSONType)
val t: ImmutableMyComplexJSONType
val immutableComplex: ImmutableMyComplexJSONType
static member ImmutableMyComplexJSONType.init: ?PropA: int[] * ?PropB: A -> ImmutableMyComplexJSONType
val immutableComplexSerialized: string