/
TupleArrayConverter.fs
105 lines (79 loc) · 3.13 KB
/
TupleArrayConverter.fs
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
namespace Newtonsoft.Json.FSharp
open System
open Microsoft.FSharp.Reflection
open Newtonsoft.Json
open Newtonsoft.Json.FSharp.Logging
/// Converter converting tuples to arrays
type TupleArrayConverter() =
inherit JsonConverter()
let logger = Logging.getLoggerByName "Newtonsoft.Json.FSharp.TupleArrayConverter"
override x.CanConvert t =
FSharpType.IsTuple t
override x.WriteJson(writer, value, serialiser) =
let values = FSharpValue.GetTupleFields(value)
serialiser.Serialize(writer, values)
override x.ReadJson(reader, t, _, serialiser) =
let read, readProp, req = (read, readProp, require) $ reader
Logger.debug logger (fun _ -> LogLine.sprintf ["type", box t] "reading json")
let itemTypes = FSharpType.GetTupleElements t
let readElements () =
let rec iter index acc =
match reader.TokenType with
| JsonToken.EndArray ->
read JsonToken.EndArray |> req |> ignore
Logger.debug logger <| fun _ ->
LogLine.sprintf
[ "path", reader.Path |> box
"token_type", reader.TokenType |> box ]
"after EndArray token, returning"
acc
| JsonToken.StartObject ->
Logger.debug logger <| fun _ ->
LogLine.sprintf
[ "path", reader.Path |> box
"token_type", reader.TokenType |> box ]
"pre-deserialise"
let value = serialiser.Deserialize (reader, itemTypes.[index])
read JsonToken.EndObject |> req |> ignore
Logger.debug logger <| fun _ ->
LogLine.sprintf
[ "path", reader.Path |> box
"token_type", reader.TokenType |> box ]
"post-deserialise"
iter (index + 1) (acc @ [value])
| JsonToken.Boolean
| JsonToken.Bytes
| JsonToken.Date
| JsonToken.Float
| JsonToken.Integer
| JsonToken.String ->
Logger.debug logger <| fun _ ->
LogLine.sprintf
[ "path", reader.Path |> box
"token_type", reader.TokenType |> box ]
"value token, pre-deserialise"
let value = serialiser.Deserialize(reader, itemTypes.[index])
reader.Read () |> ignore
Logger.debug logger <| fun _ ->
LogLine.sprintf
[ "path", reader.Path |> box
"token_type", reader.TokenType |> box ]
"value token, post-deserialise"
iter (index + 1) (acc @ [value])
| JsonToken.Null ->
failwithf "While JS tolerates nulls, F# services don't - null found at '%s'"
reader.Path
| _ as token ->
failwithf "TupleArray: Unknown intermediate token '%A' at path '%s'"
token
reader.Path
reader.Read () |> ignore
iter 0 List.empty
match reader.TokenType with
| JsonToken.StartArray ->
let values = readElements()
FSharpValue.MakeTuple (values |> List.toArray, t)
| _ ->
failwithf "TupleArray: invalid END token '%A' at path: '%s'"
reader.TokenType
reader.Path