-
-
Notifications
You must be signed in to change notification settings - Fork 36
/
Decode.fs
105 lines (81 loc) · 3.78 KB
/
Decode.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 Thoth.Json.Newtonsoft
open Thoth.Json.Core
open Newtonsoft.Json
open Newtonsoft.Json.Linq
open System.IO
[<RequireQualifiedAccess>]
module Decode =
let helpers =
{ new IDecoderHelpers<JToken> with
member _.isString jsonValue =
not (isNull jsonValue) && jsonValue.Type = JTokenType.String
member _.isNumber jsonValue =
not (isNull jsonValue)
&& (jsonValue.Type = JTokenType.Float
|| jsonValue.Type = JTokenType.Integer)
member _.isBoolean jsonValue =
not (isNull jsonValue) && jsonValue.Type = JTokenType.Boolean
member _.isNullValue jsonValue =
isNull jsonValue || jsonValue.Type = JTokenType.Null
member _.isArray jsonValue =
not (isNull jsonValue) && jsonValue.Type = JTokenType.Array
member _.isObject jsonValue =
not (isNull jsonValue) && jsonValue.Type = JTokenType.Object
member _.hasProperty fieldName jsonValue =
not (isNull jsonValue)
&& jsonValue.Type = JTokenType.Object
&& jsonValue.Value<JObject>().Properties()
|> Seq.exists (fun prop -> prop.Name = fieldName)
member _.isIntegralValue jsonValue =
not (isNull jsonValue) && (jsonValue.Type = JTokenType.Integer)
member _.asString jsonValue = jsonValue.Value<string>()
member _.asBoolean jsonValue = jsonValue.Value<bool>()
member _.asArray jsonValue =
jsonValue.Value<JArray>().Values() |> Seq.toArray
member _.asFloat jsonValue = jsonValue.Value<float>()
member _.asFloat32 jsonValue = jsonValue.Value<float32>()
member _.asInt jsonValue = jsonValue.Value<int>()
member _.getProperties jsonValue =
jsonValue.Value<JObject>().Properties()
|> Seq.map (fun prop -> prop.Name)
member _.getProperty(fieldName: string, jsonValue: JToken) =
jsonValue[fieldName]
member _.anyToString jsonValue =
if isNull jsonValue then
"null"
else
use stream = new StringWriter(NewLine = "\n")
use jsonWriter =
new JsonTextWriter(
stream,
Formatting = Formatting.Indented,
Indentation = 4
)
jsonValue.WriteTo(jsonWriter)
stream.ToString()
}
let fromValue (decoder: Decoder<'T>) =
Decode.Advanced.fromValue helpers decoder
let fromString (decoder: Decoder<'T>) =
fun value ->
try
let serializationSettings =
JsonSerializerSettings(
DateParseHandling = DateParseHandling.None,
CheckAdditionalContent = true
)
let serializer = JsonSerializer.Create(serializationSettings)
use reader = new JsonTextReader(new StringReader(value))
let res = serializer.Deserialize<JToken>(reader)
match decoder.Decode(helpers, res) with
| Ok success -> Ok success
| Error error ->
let finalError = error |> Decode.Helpers.prependPath "$"
Error(Decode.errorToString helpers finalError)
with :? JsonException as ex ->
Error("Given an invalid JSON: " + ex.Message)
let unsafeFromString (decoder: Decoder<'T>) =
fun value ->
match fromString decoder value with
| Ok x -> x
| Error e -> failwith e