Angara.Serialization


Angara.Serialization

A library that facilitates serialization on both .NET and JavaScript platforms and communication between them.
The library contains built-in serializers for a wide range of types and can easily be extended with serializers for user-defined types. Serialization formats are pluggable. The shipped implementation is based on JSON.

Example

Here is a simple example how object can be converted to JSON format and restored back.

Let's prepare a tuple of double array, integer array and string value.

open System
let x = [| 0.0; Math.PI / 6.0; 3.0 * Math.PI / 2.0  |]
let y = x |> Array.map (fun x -> sign(sin(x)))
let t = "sign(sin(x))", x, y

Next lines of code converts tuple t to a JSON format. Passing CoreSerializerResolver.Instance as a first argument means that built-in serializers will be used.

#r "Angara.Serialization.dll"
#r "Angara.Serialization.Json.dll"
open Angara.Serialization

let json = Json.FromObject(CoreSerializerResolver.Instance, t)

Text representation of resulting JSON is shown below. This JSON can be persisted to a file or transferred over network.

"{
  ":tuple<string,double array,int array>": [
    "sign(sin(x))",
    {
      ":double array": "AAAAAAAAAABlcy04UsHgP9IhM3982RJA"
    },
    {
      ":int array": "AAAAAAEAAAD/////"
    }
  ]
}"

We introduce special conventions to embed type information into serialized representation. Numeric arrays are converted to base64 representation in order to save their exact values and reduce serialized representation size. Angara.Serialization library has JavaScript component that parses and generates JSON conforming to these conventions.

Information about types is included into serialized representation. This allows to restore object without specifying it's exact type. Next snippet of code restores object from JSON and prints its type

let o = Json.ToObject<obj>(json, CoreSerializerResolver.Instance)
printfn "%A" (o.GetType())

Object is correctly restored as a tuple of two arrays and a string

System.Tuple`3[System.String,System.Double[],System.Int32[]]

It is more convenient to specify deserialized object type if you know it. Next single line of code restores tuple

let s',x',y' = 
    Json.ToObject<string * double[] * int[]>(json, CoreSerializerResolver.Instance)

Value of restored array y' is

[|0; 1; -1|]

You can find more concepts and information how to serialize user defined types in the next tutorial.

Contributing and copyright

The project is hosted on GitHub where you can report issues, fork the project and submit pull requests.

The library is available under Public Domain license, which allows modification and redistribution for both commercial and non-commercial purposes. For more information see the License file in the GitHub repository.

namespace System
val x : float []

Full name: Index.x
type Math =
  static val PI : float
  static val E : float
  static member Abs : value:sbyte -> sbyte + 6 overloads
  static member Acos : d:float -> float
  static member Asin : d:float -> float
  static member Atan : d:float -> float
  static member Atan2 : y:float * x:float -> float
  static member BigMul : a:int * b:int -> int64
  static member Ceiling : d:decimal -> decimal + 1 overload
  static member Cos : d:float -> float
  ...

Full name: System.Math
field Math.PI = 3.14159265359
val y : int []

Full name: Index.y
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val x : float
val sign : value:'T -> int (requires member get_Sign)

Full name: Microsoft.FSharp.Core.Operators.sign
val sin : value:'T -> 'T (requires member Sin)

Full name: Microsoft.FSharp.Core.Operators.sin
val t : string * float [] * int []

Full name: Index.t
namespace Angara
namespace Angara.Serialization
val json : Newtonsoft.Json.Linq.JToken

Full name: Index.json
type Json =
  private new : unit -> Json
  static member FromObject : resolver:ISerializerResolver * a:'a -> JToken
  static member FromObject : resolver:ISerializerResolver * a:'a0 * writer:IBlobWriter -> JToken
  static member Marshal : infoSet:InfoSet * writer:IBlobWriter option -> JToken
  static member ToObject : json:JToken * resolver:ISerializerResolver -> 't
  static member ToObject : json:JToken * resolver:ISerializerResolver * reader:IBlobReader -> 't
  static member Unmarshal : token:JToken * reader:IBlobReader option -> InfoSet

Full name: Angara.Serialization.Json
static member Json.FromObject : resolver:ISerializerResolver * a:'a -> Newtonsoft.Json.Linq.JToken
static member Json.FromObject : resolver:ISerializerResolver * a:'a0 * writer:IBlobWriter -> Newtonsoft.Json.Linq.JToken
type CoreSerializerResolver =
  interface ISerializerResolver
  private new : unit -> CoreSerializerResolver
  static member Instance : CoreSerializerResolver

Full name: Angara.Serialization.CoreSerializerResolver
property CoreSerializerResolver.Instance: CoreSerializerResolver
val o : obj

Full name: Index.o
static member Json.ToObject : json:Newtonsoft.Json.Linq.JToken * resolver:ISerializerResolver -> 't
static member Json.ToObject : json:Newtonsoft.Json.Linq.JToken * resolver:ISerializerResolver * reader:IBlobReader -> 't
type obj = Object

Full name: Microsoft.FSharp.Core.obj
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Object.GetType() : Type
val s' : string

Full name: Index.s'
val x' : double []

Full name: Index.x'
val y' : int []

Full name: Index.y'
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
Multiple items
val double : value:'T -> double (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.double

--------------------
type double = Double

Full name: Microsoft.FSharp.Core.double
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
Fork me on GitHub