3 people like it.

A Generic JSON Serializer for F# types

A fast generic Json serializer for F# types using TypeShape and FParsec

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
141: 
142: 
143: 
144: 
145: 
146: 
147: 
148: 
149: 
150: 
151: 
152: 
153: 
154: 
155: 
156: 
157: 
158: 
159: 
160: 
161: 
162: 
163: 
164: 
165: 
166: 
167: 
168: 
169: 
170: 
171: 
172: 
173: 
174: 
175: 
176: 
177: 
178: 
179: 
180: 
181: 
182: 
183: 
184: 
185: 
186: 
187: 
188: 
189: 
190: 
191: 
192: 
193: 
194: 
195: 
196: 
197: 
198: 
199: 
200: 
201: 
202: 
203: 
204: 
205: 
206: 
207: 
208: 
209: 
210: 
211: 
212: 
213: 
214: 
215: 
216: 
217: 
218: 
219: 
220: 
221: 
222: 
223: 
224: 
225: 
226: 
227: 
228: 
229: 
230: 
231: 
232: 
233: 
234: 
235: 
236: 
237: 
238: 
239: 
240: 
241: 
242: 
243: 
244: 
245: 
246: 
247: 
248: 
249: 
250: 
251: 
252: 
253: 
254: 
255: 
256: 
257: 
258: 
259: 
260: 
261: 
262: 
263: 
264: 
265: 
266: 
267: 
268: 
269: 
270: 
271: 
272: 
273: 
274: 
275: 
276: 
277: 
278: 
279: 
280: 
281: 
282: 
283: 
284: 
285: 
286: 
287: 
288: 
289: 
290: 
291: 
292: 
293: 
294: 
295: 
296: 
297: 
298: 
299: 
300: 
301: 
302: 
303: 
304: 
305: 
306: 
307: 
308: 
309: 
310: 
311: 
312: 
313: 
314: 
315: 
316: 
317: 
318: 
319: 
320: 
321: 
322: 
323: 
324: 
325: 
326: 
327: 
328: 
329: 
330: 
331: 
332: 
333: 
334: 
335: 
336: 
337: 
338: 
open System
open System.Text
open System.Text.RegularExpressions
open FParsec
open TypeShape
open TypeShape_Utils

// Toy Json Serializer for F# values adapted from 
// http://www.quanttec.com/fparsec/tutorial.html#parsing-json

type Parser<'T> = Parser<'T, unit>

type JsonPickler<'T> =
    {
        Printer : StringBuilder -> 'T -> unit
        Parser : Parser<'T>
    }

[<AutoOpen>]
module PrinterImpl =
    
    let [<Literal>] nullStr = "null"

    let inline append (sb : StringBuilder) (t : string) = sb.Append t |> ignore

    let private escapeChars = Regex("[\n\r\"]", RegexOptions.Compiled)
    let private matchev = 
        MatchEvaluator(fun m -> 
            match m.Value with 
            | "\n" -> "\\n" 
            | "\r" -> "\\r" 
            | "\"" -> "\\\"" 
            | v -> v)

    let escapeStr (text:string) =
        let escaped = escapeChars.Replace(text, matchev)
        "\"" + escaped + "\""

    let printField (sb : StringBuilder) (label : string) printer value =
        append sb (escapeStr label)
        append sb " : "
        printer sb value

[<AutoOpen>]
module ParserImpl =
    let spaced p = between spaces spaces p

    let inline delay (f : unit -> 'T) : Parser<'T> =
        fun _ -> Reply(f())

    let (<*>) (f : Parser<'T -> 'S>) (t : Parser<'T>) : Parser<'S> = 
        fun stream ->
            let tr = t stream
            if tr.Status <> Ok then Reply(tr.Status, tr.Error) else
            let fr = f stream
            if fr.Status <> Ok then Reply(tr.Status, tr.Error) else
            Reply(fr.Result tr.Result)

    let nullLiteral t : Parser<'T> = stringReturn "null" t
    let boolLiteral : Parser<bool> =
        (stringReturn "true"  true) <|> (stringReturn "false" false)

    let numLiteral : Parser<float> = pfloat

    let stringLiteral : Parser<string> =
        let escape =  anyOf "\"\\/bfnrt"
                      |>> function
                          | 'b' -> "\b"
                          | 'f' -> "\u000C"
                          | 'n' -> "\n"
                          | 'r' -> "\r"
                          | 't' -> "\t"
                          | c   -> string c // every other char is mapped to itself

        let unicodeEscape =
            /// converts a hex char ([0-9a-fA-F]) to its integer number (0-15)
            let hex2int c = (int c &&& 15) + (int c >>> 6)*9

            pchar 'u' >>. pipe4 hex hex hex hex (fun h3 h2 h1 h0 ->
                (hex2int h3)*4096 + (hex2int h2)*256 + (hex2int h1)*16 + hex2int h0
                |> char |> string
            )

        let escapedCharSnippet = pchar '\\' >>. (escape <|> unicodeEscape)
        let normalCharSnippet  = manySatisfy (fun c -> c <> '"' && c <> '\\')

        between (pchar '\"') (pchar '\"')
                (stringsSepBy normalCharSnippet escapedCharSnippet)

    let jsonArray parser =
        between (pchar '[') (pchar ']') (sepBy (spaced parser) (pchar ','))

    let jsonObj parser =
        between (pchar '{') (pchar '}') (spaced parser)

    let jsonField label parser = spaced (pstring (escapeStr label)) >>. pchar ':' >>. spaced parser




/// Generates a json pickler for supplied type
let rec genPickler<'T> () : JsonPickler<'T> =
    let ctx = new RecTypeManager()
    genPicklerCached<'T> ctx
    
and private genPicklerCached<'T> (ctx : RecTypeManager) : JsonPickler<'T> =
    match ctx.TryFind<JsonPickler<'T>>() with
    | Some p -> p
    | None ->
        // create a delayed uninitialized instance for recursive type definitions
        let delay (c : Cell<JsonPickler<'T>>) : JsonPickler<'T> =
            { Parser = fun s -> c.Value.Parser s ;
              Printer = fun sb -> c.Value.Printer sb }

        let _ = ctx.CreateUninitialized<JsonPickler<'T>>(delay)
        let p = genPicklerAux<'T> ctx
        ctx.Complete p
    
and private genPicklerAux<'T> (ctx : RecTypeManager) : JsonPickler<'T> =
    let mkPickler
        (printer : StringBuilder -> 'a -> unit)
        (parser : Parser<'a>) : JsonPickler<'T> =
        { Printer = unbox printer ; Parser = spaced(unbox parser) }

    let mkMemberPickler (shape : IShapeWriteMember<'Class>) =
        shape.Accept { new IWriteMemberVisitor<'Class, (StringBuilder -> 'Class -> unit) * Parser<'Class -> 'Class>> with

            member __.Visit (shape : ShapeWriteMember<'Class, 'Field>) =
                let fP = genPicklerCached<'Field> ctx
                let printer sb c = 
                    let field = shape.Project c
                    printField sb shape.Label fP.Printer field

                let parser = jsonField shape.Label fP.Parser |>> fun f c -> shape.Inject c f
                printer, parser
        }

    let combineMemberPicklers (init : Parser<'Class>) (members : IShapeWriteMember<'Class> []) =
        let printers, parsers = members |> Array.map mkMemberPickler |> Array.unzip
        let printer sb (c : 'Class) =
            for i = 0 to members.Length - 1 do
                if i > 0 then append sb ", "
                printers.[i] sb c

        let parser =
            match Array.toList parsers with
            | [] -> init
            | hd :: tl -> List.fold (fun acc p -> (pchar ',' >>. p) <*> acc) (hd <*> init) tl

        mkPickler printer parser

    let withObjBrackets (p : JsonPickler<'T>) =
        let pr = p.Printer
        { Parser = jsonObj p.Parser ; Printer = fun sb t -> append sb "{ " ; pr sb t ; append sb " }" }

    match shapeof<'T> with
    | Shape.Unit -> mkPickler (fun sb _ -> append sb nullStr) (nullLiteral ())
    | Shape.Bool -> mkPickler (fun sb b -> append sb (string b)) boolLiteral
    | Shape.Byte -> mkPickler (fun sb b -> append sb (b |> float |> string)) (numLiteral |>> byte)
    | Shape.Int32 -> mkPickler (fun sb i -> append sb (string i)) (numLiteral |>> int)
    | Shape.Int64 -> mkPickler (fun sb i -> append sb (string i)) (numLiteral |>> int64)
    | Shape.String -> mkPickler (fun sb str -> append sb (escapeStr str)) stringLiteral
    | Shape.FSharpOption s ->
        s.Accept {
            new IFSharpOptionVisitor<JsonPickler<'T>> with
                member __.Visit<'t> () =
                    let tP = genPicklerCached<'t> ctx
                    let printer (sb : StringBuilder) (inp : 't option) =
                        match inp with
                        | None -> append sb nullStr
                        | Some t -> tP.Printer sb t

                    let nP = nullLiteral None
                    let sP = tP.Parser |>> Some
                    let parser = nP <|> sP
                    mkPickler printer parser
        }

    | Shape.FSharpList s ->
        s.Accept {
            new IFSharpListVisitor<JsonPickler<'T>> with
                member __.Visit<'t> () =
                    let eP = genPicklerCached<'t> ctx
                    let printer sb (ts : 't list) =
                        append sb "["
                        match ts with
                        | [] -> ()
                        | hd :: tl ->
                            eP.Printer sb hd
                            for t in tl do 
                                append sb ", "
                                eP.Printer sb t

                        append sb "]"

                    let parser = jsonArray eP.Parser

                    mkPickler printer parser
        }

    | Shape.Array s when s.Rank = 1 ->
        s.Accept {
            new IArrayVisitor<JsonPickler<'T>> with
                member __.Visit<'t> _ =
                    let eP = genPicklerCached<'t> ctx
                    let printer sb (ts : 't []) =
                        append sb "["
                        if ts.Length > 0 then
                            eP.Printer sb ts.[0]
                            for i in 1 .. ts.Length - 1 do
                                append sb ", "
                                eP.Printer sb ts.[i]

                        append sb "]"

                    let parser = jsonArray eP.Parser |>> Array.ofList

                    mkPickler printer parser
        }

    | Shape.FSharpMap s ->
        s.Accept {
            new IFSharpMapVisitor<JsonPickler<'T>> with
                member __.Visit<'k,'v when 'k : comparison> () =
                    if typeof<'k> <> typeof<string> then failwithf "Type '%O' is not supported" typeof<'T>
                    let vp = genPicklerCached<'v> ctx
                    let printer sb (m : Map<string, 'v>) =
                        append sb "{ "
                        let mutable first = true
                        for kv in m do
                            if first then first <- false else append sb ", "
                            append sb (escapeStr kv.Key)
                            append sb " : "
                            vp.Printer sb kv.Value

                        append sb " }"

                    let parser =
                        let keyValue = stringLiteral .>> spaced (pchar ':') .>>. vp.Parser
                        sepBy keyValue (spaced (pchar ',')) |>> Map.ofList |> jsonObj

                    mkPickler printer parser
        }

    | Shape.Tuple (:? ShapeTuple<'T> as shape) ->
        combineMemberPicklers (delay shape.CreateUninitialized) shape.Elements
        |> withObjBrackets

    | Shape.FSharpRecord (:? ShapeFSharpRecord<'T> as shape) ->
        combineMemberPicklers (delay shape.CreateUninitialized) shape.Fields
        |> withObjBrackets

    | Shape.FSharpUnion (:? ShapeFSharpUnion<'T> as shape) ->
        let mkUnionCaseInfo (case : ShapeFSharpUnionCase<'T>) =
            let hasFields = case.Fields.Length > 0
            let pickler = combineMemberPicklers (delay case.CreateUninitialized) case.Fields
            let parser = if hasFields then spaced (pchar ',') >>. pickler.Parser else pickler.Parser
            let printer sb t = (if hasFields then append sb ", ") ; pickler.Printer sb t
            escapeStr case.CaseInfo.Name, printer, parser

        let caseInfo = shape.UnionCases |> Array.map mkUnionCaseInfo

        {
            Printer = 
                fun (sb:StringBuilder) (t:'T) ->
                    let tag = shape.GetTag t
                    let label, printer, _ = caseInfo.[tag]
                    printField sb "__tag" append label
                    printer sb t

            Parser =
                jsonField "__tag" stringLiteral >>= 
                    fun tag -> 
                        let t = shape.GetTag tag 
                        let _,_,parser = caseInfo.[t]
                        parser

        } |> withObjBrackets

    | _ -> failwithf "unsupported type '%O'" typeof<'T>

//-----------------------------------
// Serialization functions

let serialize (pickler : JsonPickler<'T>) (value : 'T) : string =
    let sb = new StringBuilder()
    pickler.Printer sb value
    sb.ToString()

let deserialize (pickler : JsonPickler<'T>) (json : string) : 'T =
    match run pickler.Parser json with
    | Success(r,_,_) -> r
    | Failure(msg,_,_) -> failwithf "Parse error: %s" msg


//--------------------------
// Examples

let p1 = genPickler<int * int list>()

serialize p1 (1, [2;3;4])
|> deserialize p1
// "{ "Item1" : 1, "Item2" : [2, 3, 4] }"

let p2 = genPickler<int * string list option * string ref>()

serialize p2 (1, Some(["a";"b";"c"]), ref "foo")
|> deserialize p2
// "{ "Item1" : 1, "Item2" : ["a", "b", "c"], "Item3" : { "contents" : "foo" } }"

type Foo = { A : int ; B : string }

type Bar =
    | Foo of Foo
    | Bar of int
    | C
    | D of string option
    | E of Map<string, int>

let p3 = genPickler<Bar list []>()

serialize p3 [| [] ; [C ; D None] ; [Foo { A = 42 ; B = "12" }] ; [E (Map.ofList [("foo", 42)])]|]
|> deserialize p3
// "[[], [{ "__tag" : "C" }, { "__tag" : "D", "Item" : null }], [{ "__tag" : "Foo", "Item" : { "A" : 42, "B" : "12
// " } }], [{ "__tag" : "E", "Item" : { "foo" : 42 } }]]"

// Recursive type serialization

type BinTree<'T> = Leaf | Node of 'T * BinTree<'T> * BinTree<'T>

let p4 = genPickler<BinTree<int>> ()

serialize p4 (Node(3, Node(1, Leaf, Node(2, Leaf,Leaf)), Leaf))
|> deserialize p4

// "{ "__tag" : "Node", "Item1" : 3, "Item2" : { "__tag" : "Node", "Item1" : 1, "Item2" : { "__tag" : "Leaf" }, 
//    "Item3" : { "__tag" : "Node", "Item1" : 2, "Item2" : { "__tag" : "Leaf" }, "Item3" : { "__tag" : "Leaf" } } },
//    "Item3" : { "__tag" : "Leaf" } }"
namespace System
namespace System.Text
namespace System.Text.RegularExpressions
namespace FParsec
module TypeShape
module TypeShape_Utils
Multiple items
type Parser<'T> = Parser<'T,unit>

Full name: Script.Parser<_>

--------------------
type Parser<'Result,'UserState> = CharStream<'UserState> -> Reply<'Result>

Full name: FParsec.Primitives.Parser<_,_>
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
type JsonPickler<'T> =
  {Printer: StringBuilder -> 'T -> unit;
   Parser: Parser<'T>;}

Full name: Script.JsonPickler<_>
JsonPickler.Printer: StringBuilder -> 'T -> unit
Multiple items
type StringBuilder =
  new : unit -> StringBuilder + 5 overloads
  member Append : value:string -> StringBuilder + 18 overloads
  member AppendFormat : format:string * arg0:obj -> StringBuilder + 4 overloads
  member AppendLine : unit -> StringBuilder + 1 overload
  member Capacity : int with get, set
  member Chars : int -> char with get, set
  member Clear : unit -> StringBuilder
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EnsureCapacity : capacity:int -> int
  member Equals : sb:StringBuilder -> bool
  ...

Full name: System.Text.StringBuilder

--------------------
StringBuilder() : unit
StringBuilder(capacity: int) : unit
StringBuilder(value: string) : unit
StringBuilder(value: string, capacity: int) : unit
StringBuilder(capacity: int, maxCapacity: int) : unit
StringBuilder(value: string, startIndex: int, length: int, capacity: int) : unit
Multiple items
JsonPickler.Parser: Parser<'T>

--------------------
type Parser<'T> = Parser<'T,unit>

Full name: Script.Parser<_>

--------------------
type Parser<'Result,'UserState> = CharStream<'UserState> -> Reply<'Result>

Full name: FParsec.Primitives.Parser<_,_>
Multiple items
type AutoOpenAttribute =
  inherit Attribute
  new : unit -> AutoOpenAttribute
  new : path:string -> AutoOpenAttribute
  member Path : string

Full name: Microsoft.FSharp.Core.AutoOpenAttribute

--------------------
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
Multiple items
type LiteralAttribute =
  inherit Attribute
  new : unit -> LiteralAttribute

Full name: Microsoft.FSharp.Core.LiteralAttribute

--------------------
new : unit -> LiteralAttribute
val nullStr : string

Full name: Script.PrinterImpl.nullStr
val append : sb:StringBuilder -> t:string -> unit

Full name: Script.PrinterImpl.append
val sb : StringBuilder
val t : string
Multiple items
val string : value:'T -> string

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

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

Full name: Microsoft.FSharp.Core.string
StringBuilder.Append(value: char []) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: obj) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: uint64) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: uint32) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: uint16) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: decimal) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: float) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: float32) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: int64) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: int) : StringBuilder
   (+0 other overloads)
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val private escapeChars : Regex

Full name: Script.PrinterImpl.escapeChars
Multiple items
type Regex =
  new : pattern:string -> Regex + 1 overload
  member GetGroupNames : unit -> string[]
  member GetGroupNumbers : unit -> int[]
  member GroupNameFromNumber : i:int -> string
  member GroupNumberFromName : name:string -> int
  member IsMatch : input:string -> bool + 1 overload
  member Match : input:string -> Match + 2 overloads
  member Matches : input:string -> MatchCollection + 1 overload
  member Options : RegexOptions
  member Replace : input:string * replacement:string -> string + 5 overloads
  ...

Full name: System.Text.RegularExpressions.Regex

--------------------
Regex(pattern: string) : unit
Regex(pattern: string, options: RegexOptions) : unit
type RegexOptions =
  | None = 0
  | IgnoreCase = 1
  | Multiline = 2
  | ExplicitCapture = 4
  | Compiled = 8
  | Singleline = 16
  | IgnorePatternWhitespace = 32
  | RightToLeft = 64
  | ECMAScript = 256
  | CultureInvariant = 512

Full name: System.Text.RegularExpressions.RegexOptions
field RegexOptions.Compiled = 8
val private matchev : MatchEvaluator

Full name: Script.PrinterImpl.matchev
type MatchEvaluator =
  delegate of Match -> string

Full name: System.Text.RegularExpressions.MatchEvaluator
val m : Match
property Capture.Value: string
val v : string
val escapeStr : text:string -> string

Full name: Script.PrinterImpl.escapeStr
val text : string
val escaped : string
Regex.Replace(input: string, evaluator: MatchEvaluator) : string
Regex.Replace(input: string, replacement: string) : string
Regex.Replace(input: string, evaluator: MatchEvaluator, count: int) : string
Regex.Replace(input: string, replacement: string, count: int) : string
Regex.Replace(input: string, evaluator: MatchEvaluator, count: int, startat: int) : string
Regex.Replace(input: string, replacement: string, count: int, startat: int) : string
val printField : sb:StringBuilder -> label:string -> printer:(StringBuilder -> 'a -> 'b) -> value:'a -> 'b

Full name: Script.PrinterImpl.printField
val label : string
val printer : (StringBuilder -> 'a -> 'b)
val value : 'a
val spaced : p:Parser<'a,'b> -> Parser<'a,'b>

Full name: Script.ParserImpl.spaced
val p : Parser<'a,'b>
val between : Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'c,'u>

Full name: FParsec.Primitives.between
val spaces : Parser<unit,'u>

Full name: FParsec.CharParsers.spaces
val delay : f:(unit -> 'T) -> CharStream<unit> -> Reply<'T>

Full name: Script.ParserImpl.delay
val f : (unit -> 'T)
Multiple items
type Reply<'TResult> =
  struct
    new : result:'TResult -> Reply<'TResult> + 2 overloads
    val Error : ErrorMessageList
    val Result : 'TResult
    val Status : ReplyStatus
    member Equals : other:obj -> bool + 1 overload
    member GetHashCode : unit -> int
  end

Full name: FParsec.Reply<_>

--------------------
Reply()
Reply(result: 'TResult) : unit
Reply(status: ReplyStatus, error: ErrorMessageList) : unit
Reply(status: ReplyStatus, result: 'TResult, error: ErrorMessageList) : unit
val f : Parser<('T -> 'S)>
val t : Parser<'T>
val stream : CharStream<unit>
val tr : Reply<'T>
field Reply.Status
val Ok : ReplyStatus

Full name: FParsec.Primitives.Ok
field Reply.Error
val fr : Reply<('T -> 'S)>
field Reply.Result
val nullLiteral : t:'T -> Parser<'T>

Full name: Script.ParserImpl.nullLiteral
val t : 'T
val stringReturn : string -> 'a -> Parser<'a,'u>

Full name: FParsec.CharParsers.stringReturn
val boolLiteral : Parser<bool>

Full name: Script.ParserImpl.boolLiteral
type bool = Boolean

Full name: Microsoft.FSharp.Core.bool
val numLiteral : Parser<float>

Full name: Script.ParserImpl.numLiteral
Multiple items
val float : value:'T -> float (requires member op_Explicit)

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

--------------------
type float = Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
val pfloat : Parser<float,'u>

Full name: FParsec.CharParsers.pfloat
val stringLiteral : Parser<string>

Full name: Script.ParserImpl.stringLiteral
val escape : Parser<string,unit>
val anyOf : seq<char> -> Parser<char,'u>

Full name: FParsec.CharParsers.anyOf
val c : char
val unicodeEscape : Parser<string,unit>
val hex2int : (char -> int)


 converts a hex char ([0-9a-fA-F]) to its integer number (0-15)
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<_>
val pchar : char -> Parser<char,'u>

Full name: FParsec.CharParsers.pchar
val pipe4 : Parser<'a,'u> -> Parser<'b,'u> -> Parser<'c,'u> -> Parser<'d,'u> -> ('a -> 'b -> 'c -> 'd -> 'e) -> Parser<'e,'u>

Full name: FParsec.Primitives.pipe4
val hex : Parser<char,'u>

Full name: FParsec.CharParsers.hex
val h3 : char
val h2 : char
val h1 : char
val h0 : char
Multiple items
val char : value:'T -> char (requires member op_Explicit)

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

--------------------
type char = Char

Full name: Microsoft.FSharp.Core.char
val escapedCharSnippet : Parser<string,unit>
val normalCharSnippet : Parser<string,unit>
val manySatisfy : (char -> bool) -> Parser<string,'u>

Full name: FParsec.CharParsers.manySatisfy
val stringsSepBy : Parser<string,'u> -> Parser<string,'u> -> Parser<string,'u>

Full name: FParsec.CharParsers.stringsSepBy
val jsonArray : parser:Parser<'a,'b> -> Parser<'a list,'b>

Full name: Script.ParserImpl.jsonArray
val parser : Parser<'a,'b>
val sepBy : Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>

Full name: FParsec.Primitives.sepBy
val jsonObj : parser:Parser<'a,'b> -> Parser<'a,'b>

Full name: Script.ParserImpl.jsonObj
val jsonField : label:string -> parser:Parser<'a,'b> -> Parser<'a,'b>

Full name: Script.ParserImpl.jsonField
val pstring : string -> Parser<string,'u>

Full name: FParsec.CharParsers.pstring
val genPickler : unit -> JsonPickler<'T>

Full name: Script.genPickler


 Generates a json pickler for supplied type
val ctx : RecTypeManager
Multiple items
type RecTypeManager =
  interface IDisposable
  new : unit -> RecTypeManager
  private new : parentCache:TypeCache option -> RecTypeManager
  member Complete : value:'T -> 'T
  member CreateUninitialized : delay:(Cell<'T> -> 'T) -> 'T
  member private GetGeneratedValues : unit -> (Type * obj) []
  member TryFind : unit -> 'T option
  member private ParentCache : TypeCache option

Full name: TypeShape_Utils.RecTypeManager

--------------------
new : unit -> RecTypeManager
val private genPicklerCached : ctx:RecTypeManager -> JsonPickler<'T>

Full name: Script.genPicklerCached
member RecTypeManager.TryFind : unit -> 'T option
union case Option.Some: Value: 'T -> Option<'T>
val p : JsonPickler<'T>
union case Option.None: Option<'T>
val delay : (Cell<JsonPickler<'T>> -> JsonPickler<'T>)
val c : Cell<JsonPickler<'T>>
type Cell<'T> =
  private new : container:'T option ref -> Cell<'T>
  member IsValueCreated : bool
  member Value : 'T

Full name: TypeShape_Utils.Cell<_>
val s : CharStream<unit>
property Cell.Value: JsonPickler<'T>
JsonPickler.Parser: Parser<'T>
member RecTypeManager.CreateUninitialized : delay:(Cell<'T> -> 'T) -> 'T
val private genPicklerAux : ctx:RecTypeManager -> JsonPickler<'T>

Full name: Script.genPicklerAux
member RecTypeManager.Complete : value:'T -> 'T
val mkPickler : ((StringBuilder -> 'a -> unit) -> Parser<'a> -> JsonPickler<'T>)
val printer : (StringBuilder -> 'a -> unit)
val parser : Parser<'a>
val unbox : value:obj -> 'T

Full name: Microsoft.FSharp.Core.Operators.unbox
val mkMemberPickler : (IShapeWriteMember<'Class> -> (StringBuilder -> 'Class -> unit) * Parser<('Class -> 'Class)>)
val shape : IShapeWriteMember<'Class>
type IShapeWriteMember<'Record> =
  interface
    inherit IShapeMember<'Record>
    abstract member Accept : IWriteMemberVisitor<'Record,'R> -> 'R
  end

Full name: TypeShape.IShapeWriteMember<_>
Multiple items
type ClassAttribute =
  inherit Attribute
  new : unit -> ClassAttribute

Full name: Microsoft.FSharp.Core.ClassAttribute

--------------------
new : unit -> ClassAttribute
abstract member IShapeMember.Accept : IMemberVisitor<'DeclaringType,'R> -> 'R
abstract member IShapeWriteMember.Accept : IWriteMemberVisitor<'Record,'R> -> 'R
type IWriteMemberVisitor<'TRecord,'R> =
  interface
    abstract member Visit : ShapeWriteMember<'TRecord,'Field> -> 'R
  end

Full name: TypeShape.IWriteMemberVisitor<_,_>
val shape : ShapeWriteMember<'Class,'a>
type ShapeWriteMember<'DeclaringType,'MemberType> =
  interface IShapeWriteMember<'DeclaringType>
  interface IShapeMember<'DeclaringType>
  private new : label:string * memberInfo:MemberInfo * path:MemberInfo [] * readOnly:ShapeMember<'DeclaringType,'MemberType> -> ShapeWriteMember<'DeclaringType,'MemberType>
  member Inject : instance:'DeclaringType -> field:'MemberType -> 'DeclaringType
  member InjectExpr : instance:Expr<'DeclaringType> -> field:Expr<'MemberType> -> Expr<'DeclaringType>
  member Project : instance:'DeclaringType -> 'MemberType
  member ProjectExpr : instance:Expr<'DeclaringType> -> Expr<'MemberType>
  member IsPublic : bool
  member IsStructMember : bool
  member Label : string
  ...

Full name: TypeShape.ShapeWriteMember<_,_>
val fP : JsonPickler<'a>
val printer : (StringBuilder -> 'Class -> unit)
val c : 'Class
val field : 'a
member ShapeWriteMember.Project : instance:'DeclaringType -> 'MemberType
property ShapeWriteMember.Label: string
JsonPickler.Printer: StringBuilder -> 'a -> unit
val parser : Parser<('Class -> 'Class),unit>
JsonPickler.Parser: Parser<'a>
val f : 'a
member ShapeWriteMember.Inject : instance:'DeclaringType -> field:'MemberType -> 'DeclaringType
val combineMemberPicklers : (Parser<'Class> -> IShapeWriteMember<'Class> [] -> JsonPickler<'T>)
val init : Parser<'Class>
val members : IShapeWriteMember<'Class> []
val printers : (StringBuilder -> 'Class -> unit) []
val parsers : Parser<('Class -> 'Class)> []
Multiple items
union case TypeShapeInfo.Array: element: Type * rank: int -> TypeShapeInfo

--------------------
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 unzip : array:('T1 * 'T2) [] -> 'T1 [] * 'T2 []

Full name: Microsoft.FSharp.Collections.Array.unzip
val i : int
property Array.Length: int
val parser : Parser<'Class>
val toList : array:'T [] -> 'T list

Full name: Microsoft.FSharp.Collections.Array.toList
val hd : Parser<('Class -> 'Class)>
val tl : Parser<('Class -> 'Class)> list
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member GetSlice : startIndex:int option * endIndex:int option -> 'T list
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State

Full name: Microsoft.FSharp.Collections.List.fold
val acc : Parser<'Class>
val p : Parser<('Class -> 'Class),unit>
val withObjBrackets : (JsonPickler<'T> -> JsonPickler<'T>)
val pr : (StringBuilder -> 'T -> unit)
val shapeof<'T> : TypeShape<'T>

Full name: TypeShape.shapeof
module Shape

from TypeShape
active recognizer Unit: TypeShape -> unit option

Full name: TypeShape.Shape.( |Unit|_| )
active recognizer Bool: TypeShape -> unit option

Full name: TypeShape.Shape.( |Bool|_| )
val b : bool
active recognizer Byte: TypeShape -> unit option

Full name: TypeShape.Shape.( |Byte|_| )
val b : byte
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

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

--------------------
type byte = Byte

Full name: Microsoft.FSharp.Core.byte
active recognizer Int32: TypeShape -> unit option

Full name: TypeShape.Shape.( |Int32|_| )
active recognizer Int64: TypeShape -> unit option

Full name: TypeShape.Shape.( |Int64|_| )
val i : int64
Multiple items
val int64 : value:'T -> int64 (requires member op_Explicit)

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

--------------------
type int64 = Int64

Full name: Microsoft.FSharp.Core.int64

--------------------
type int64<'Measure> = int64

Full name: Microsoft.FSharp.Core.int64<_>
active recognizer String: TypeShape -> unit option

Full name: TypeShape.Shape.( |String|_| )
val str : string
active recognizer FSharpOption: TypeShape -> IShapeFSharpOption option

Full name: TypeShape.Shape.( |FSharpOption|_| )
val s : IShapeFSharpOption
abstract member IShapeFSharpOption.Accept : IFSharpOptionVisitor<'R> -> 'R
type IFSharpOptionVisitor<'R> =
  interface
    abstract member Visit : unit -> 'R
  end

Full name: TypeShape.IFSharpOptionVisitor<_>
val tP : JsonPickler<'t>
val printer : (StringBuilder -> 't option -> unit)
val inp : 't option
type 'T option = Option<'T>

Full name: Microsoft.FSharp.Core.option<_>
val t : 't
JsonPickler.Printer: StringBuilder -> 't -> unit
val nP : Parser<'t option>
val sP : Parser<'t option,unit>
JsonPickler.Parser: Parser<'t>
val parser : Parser<'t option,unit>
active recognizer FSharpList: TypeShape -> IShapeFSharpList option

Full name: TypeShape.Shape.( |FSharpList|_| )
val s : IShapeFSharpList
abstract member IShapeFSharpList.Accept : IFSharpListVisitor<'R> -> 'R
type IFSharpListVisitor<'R> =
  interface
    abstract member Visit : unit -> 'R
  end

Full name: TypeShape.IFSharpListVisitor<_>
val eP : JsonPickler<'t>
val printer : (StringBuilder -> 't list -> unit)
val ts : 't list
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
val hd : 't
val tl : 't list
val parser : Parser<'t list,unit>
active recognizer Array: TypeShape -> IShapeArray option

Full name: TypeShape.Shape.( |Array|_| )
val s : IShapeArray
property IShapeArray.Rank: int
abstract member IShapeArray.Accept : IArrayVisitor<'R> -> 'R
type IArrayVisitor<'R> =
  interface
    abstract member Visit : rank:int -> 'R
  end

Full name: TypeShape.IArrayVisitor<_>
val printer : (StringBuilder -> 't [] -> unit)
val ts : 't []
val i : int32
val parser : Parser<'t [],unit>
val ofList : list:'T list -> 'T []

Full name: Microsoft.FSharp.Collections.Array.ofList
active recognizer FSharpMap: TypeShape -> IShapeFSharpMap option

Full name: TypeShape.Shape.( |FSharpMap|_| )
val s : IShapeFSharpMap
abstract member IShapeFSharpMap.Accept : IFSharpMapVisitor<'R> -> 'R
type IFSharpMapVisitor<'R> =
  interface
    abstract member Visit : unit -> 'R
  end

Full name: TypeShape.IFSharpMapVisitor<_>
val typeof<'T> : Type

Full name: Microsoft.FSharp.Core.Operators.typeof
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
val vp : JsonPickler<'v>
val printer : (StringBuilder -> Map<string,'v> -> unit)
val m : Map<string,'v>
Multiple items
module Map

from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> =
  interface IEnumerable
  interface IComparable
  interface IEnumerable<KeyValuePair<'Key,'Value>>
  interface ICollection<KeyValuePair<'Key,'Value>>
  interface IDictionary<'Key,'Value>
  new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
  member Add : key:'Key * value:'Value -> Map<'Key,'Value>
  member ContainsKey : key:'Key -> bool
  override Equals : obj -> bool
  member Remove : key:'Key -> Map<'Key,'Value>
  ...

Full name: Microsoft.FSharp.Collections.Map<_,_>

--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val mutable first : bool
val kv : Collections.Generic.KeyValuePair<string,'v>
property Collections.Generic.KeyValuePair.Key: string
JsonPickler.Printer: StringBuilder -> 'v -> unit
property Collections.Generic.KeyValuePair.Value: 'v
val parser : Parser<Map<string,'v>,unit>
val keyValue : Parser<(string * 'v),unit>
JsonPickler.Parser: Parser<'v>
val ofList : elements:('Key * 'T) list -> Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.ofList
active recognizer Tuple: TypeShape -> IShapeTuple option

Full name: TypeShape.Shape.( |Tuple|_| )
type ShapeTuple<'Tuple> =
  interface IShapeTuple
  private new : unit -> ShapeTuple<'Tuple>
  member CreateUninitialized : unit -> 'Tuple
  member CreateUninitializedExpr : unit -> Expr<'Tuple>
  member Elements : IShapeWriteMember<'Tuple> []

Full name: TypeShape.ShapeTuple<_>
val shape : ShapeTuple<'T>
member ShapeTuple.CreateUninitialized : unit -> 'Tuple
property ShapeTuple.Elements: IShapeWriteMember<'T> []
active recognizer FSharpRecord: TypeShape -> IShapeFSharpRecord option

Full name: TypeShape.Shape.( |FSharpRecord|_| )
type ShapeFSharpRecord<'Record> =
  interface IShapeFSharpRecord
  private new : unit -> ShapeFSharpRecord<'Record>
  member CreateUninitialized : unit -> 'Record
  member CreateUninitializedExpr : unit -> Expr<'Record>
  member Fields : IShapeWriteMember<'Record> []

Full name: TypeShape.ShapeFSharpRecord<_>
val shape : ShapeFSharpRecord<'T>
member ShapeFSharpRecord.CreateUninitialized : unit -> 'Record
property ShapeFSharpRecord.Fields: IShapeWriteMember<'T> []
active recognizer FSharpUnion: TypeShape -> IShapeFSharpUnion option

Full name: TypeShape.Shape.( |FSharpUnion|_| )
type ShapeFSharpUnion<'U> =
  interface IShapeFSharpUnion
  private new : unit -> ShapeFSharpUnion<'U>
  member GetTag : caseName:string -> int
  member GetTag : union:'U -> int
  member GetTagExpr : union:Expr<'U> -> Expr<int>
  member UnionCases : ShapeFSharpUnionCase<'U> []

Full name: TypeShape.ShapeFSharpUnion<_>
val shape : ShapeFSharpUnion<'T>
val mkUnionCaseInfo : (ShapeFSharpUnionCase<'T> -> string * (StringBuilder -> 'T -> unit) * Parser<'T,unit>)
val case : ShapeFSharpUnionCase<'T>
type ShapeFSharpUnionCase<'Union> =
  interface IShapeFSharpUnionCase
  private new : uci:UnionCaseInfo -> ShapeFSharpUnionCase<'Union>
  member CreateUninitialized : unit -> 'Union
  member CreateUninitializedExpr : unit -> Expr<'Union>
  member CaseInfo : UnionCaseInfo
  member Fields : IShapeWriteMember<'Union> []

Full name: TypeShape.ShapeFSharpUnionCase<_>
val hasFields : bool
property ShapeFSharpUnionCase.Fields: IShapeWriteMember<'T> []
val pickler : JsonPickler<'T>
member ShapeFSharpUnionCase.CreateUninitialized : unit -> 'Union
val parser : Parser<'T,unit>
val printer : (StringBuilder -> 'T -> unit)
property ShapeFSharpUnionCase.CaseInfo: Reflection.UnionCaseInfo
property Reflection.UnionCaseInfo.Name: string
val caseInfo : (string * (StringBuilder -> 'T -> unit) * Parser<'T,unit>) []
property ShapeFSharpUnion.UnionCases: ShapeFSharpUnionCase<'T> []
val tag : int
member ShapeFSharpUnion.GetTag : caseName:string -> int
member ShapeFSharpUnion.GetTag : union:'U -> int
val tag : string
val t : int
val serialize : pickler:JsonPickler<'T> -> value:'T -> string

Full name: Script.serialize
val value : 'T
StringBuilder.ToString() : string
StringBuilder.ToString(startIndex: int, length: int) : string
val deserialize : pickler:JsonPickler<'T> -> json:string -> 'T

Full name: Script.deserialize
val json : string
val run : Parser<'Result,unit> -> string -> ParserResult<'Result,unit>

Full name: FParsec.CharParsers.run
union case ParserResult.Success: 'Result * 'UserState * Position -> ParserResult<'Result,'UserState>
val r : 'T
union case ParserResult.Failure: string * ParserError * 'UserState -> ParserResult<'Result,'UserState>
val msg : string
val p1 : JsonPickler<int * int list>

Full name: Script.p1
val p2 : JsonPickler<int * string list option * string ref>

Full name: Script.p2
Multiple items
val ref : value:'T -> 'T ref

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

--------------------
type 'T ref = Ref<'T>

Full name: Microsoft.FSharp.Core.ref<_>
type Foo =
  {A: int;
   B: string;}

Full name: Script.Foo
Foo.A: int
Foo.B: string
Multiple items
union case Bar.Bar: int -> Bar

--------------------
type Bar =
  | Foo of Foo
  | Bar of int
  | C
  | D of string option
  | E of Map<string,int>

Full name: Script.Bar
Multiple items
union case Bar.Foo: Foo -> Bar

--------------------
type Foo =
  {A: int;
   B: string;}

Full name: Script.Foo
union case Bar.C: Bar
union case Bar.D: string option -> Bar
union case Bar.E: Map<string,int> -> Bar
val p3 : JsonPickler<Bar list []>

Full name: Script.p3
type BinTree<'T> =
  | Leaf
  | Node of 'T * BinTree<'T> * BinTree<'T>

Full name: Script.BinTree<_>
union case BinTree.Leaf: BinTree<'T>
union case BinTree.Node: 'T * BinTree<'T> * BinTree<'T> -> BinTree<'T>
val p4 : JsonPickler<BinTree<int>>

Full name: Script.p4
Raw view Test code New version

More information

Link:http://fssnip.net/7RI
Posted:7 years ago
Author:Eirik Tsarpalis
Tags: json , serialization , typeshape