Library for working with JSON in a type safe manner, this libs is the .NET version of Thoth.Json.
Learn more about Thoth.Json here.
Home Page: https://thoth-org.github.io/Thoth.Json/#.Net-and-NetCore-support
License: MIT License
Library for working with JSON in a type safe manner, this libs is the .NET version of Thoth.Json.
Learn more about Thoth.Json here.
specifically when the input string contains new lines, tab characters, quote characters etc.
How to reproduce:
#r "nuget:Thoth.Json.Net"
open Thoth.Json.Net
let decoder = Decode.keyValuePairs Decode.int
Decode.unsafeFromString decoder """ { "a": 1, "b": 2, "c": false } """
System.Exception : Error at: `$`
Expecting an int but instead got: false
at Thoth.Json.Net.Decode.unsafeFromString[T](FSharpFunc`2 decoder, String value)
The problem is, the error does not show the problem occured when parsing "c"
property of an object.
Projects that upgrades from 3.5.1 to 3.6.0 and depends on NuGet's built with 3.5.1 breaks with runtime error: "Method not found: 'Microsoft.FSharp.Core.FSharpResult2<Int32,System.Tuple
2<System.String,Thoth.Json.Net.ErrorReason>> Thoth.Json.Net.Decode.int(System.String, Newtonsoft.Json.Linq.JToken)'."
Just a heads up. I have no idea what the problem is. Recompiling dependencies with 3.6.0 seems to fix the problem.
Not sure if it's related with the problems you had in SAFE-Stack/SAFE-BookStore#388 but there seems to be an issue with the FSharp.Core dependency in the Thoth.Json.Net package. This is causing an issue in one of my projects when trying to use Thoth.Json.Net 3.0.0-beta-005.
In Nuget, the version of the FSharp.Core dependency is 0.0.0:
@forki do you have any idea why this happens? Maybe it's related with the multiple target frameworks?
Currently encoding and decoding of ordinary enum
s like System.DayOfTheWeek
require own extra coders, e.g.
module Encode =
let dayofWeek (value: System.DayOfWeek) : JsonValue =
LanguagePrimitives.EnumToValue (value)
|>JValue :> JsonValue
module Decode =
module Helpers =
let inline isInteger (token: JsonValue) = not(isNull token) && (token.Type = JTokenType.Integer)
let inline isString (token: JsonValue) = not(isNull token) && token.Type = JTokenType.String
let inline asString (token: JsonValue): string = token.Value<string>()
let dayofWeek : Decoder<System.DayOfWeek> =
fun path token ->
if Helpers.isInteger token then
// TODO: Is not enough to convert to int directly? Maybe these checks hurt performance?
let value = token.Value<decimal> ()
if value >= (decimal System.Int32.MinValue) && value <= (decimal System.Int32.MaxValue) then
Ok (LanguagePrimitives.EnumOfValue ((int32) value))
else
(path, BadPrimitiveExtra("an int", token, "Value was either too large or too small for an int")) |> Error
elif Helpers.isString token then
match System.Int32.TryParse (Helpers.asString token, NumberStyles.Any, CultureInfo.InvariantCulture) with
| true, x -> Ok <| LanguagePrimitives.EnumOfValue(x)
| _ -> (path, BadPrimitive("an int", token)) |> Error
else
(path, BadPrimitive("an int", token)) |> Error
This works pretty good, however I would love to have generic Enum support, either direclty in Thoth.Json or as extra coder.
This naive approach fail:
module Encode =
let enumInt (value: 'T when 'T:enum<int>) : JsonValue =
LanguagePrimitives.EnumToValue (value)
|>JValue :> JsonValue
module Decode =
module Helpers =
let inline isInteger (token: JsonValue) = not(isNull token) && (token.Type = JTokenType.Integer)
let inline isString (token: JsonValue) = not(isNull token) && token.Type = JTokenType.String
let inline asString (token: JsonValue): string = token.Value<string>()
let enumInt : Decoder<'T> when 'T:enum<int> =
fun path token ->
if Helpers.isInteger token then
// TODO: Is not enough to convert to int directly? Maybe these checks hurt performance?
let value = token.Value<decimal> ()
if value >= (decimal System.Int32.MinValue) && value <= (decimal System.Int32.MaxValue) then
Ok (LanguagePrimitives.EnumOfValue ((int32) value))
else
(path, BadPrimitiveExtra("an int", token, "Value was either too large or too small for an int")) |> Error
elif Helpers.isString token then
match System.Int32.TryParse (Helpers.asString token, NumberStyles.Any, CultureInfo.InvariantCulture) with
| true, x -> Ok <| LanguagePrimitives.EnumOfValue(x)
| _ -> (path, BadPrimitive("an int", token)) |> Error
else
(path, BadPrimitive("an int", token)) |> Error
While the encoders and decoders work, they cannot be added withCustom
, and I also failt adding them directly in Thoth.Json.Net.
It worked before in 2.x, maybe this just a special case of #9, where all unknown types case were handled by NewtonSoft.Json.
The idea is to remove this warning
/// ATTENTION: Use this only when other arguments (isCamelCase, extra) don't change
In order to do that, we could use the Type
and arguments state in order to generate the key instead of just the cache.
Hi,
I just ran into an issue when attempting to decode json (Encoded with Thoth.Json.Net) using Elm's decoders: Thoth.Json.Net appears to encode numbers as strings whereas Elm's decoder is expecting number within the json.
Some code from Encode.fs:
let uint64 (value : uint64) : JsonValue = JValue(value.ToString(CultureInfo.InvariantCulture)) :> JsonValue
Is this an oversight or by design?
My expectation was that numbers would be encoded without quotes to the json.
Hi,
I have encountered the following inconsistency that I think might be a bug in Thoth.Json. Let's say we have an optional object in a JSON document. The field that holds it is decoded as optional. However, if I access some values of the object in its decoder (other than assigning them to some fields) the decoder crashes with a nullref. This happens only if the json document contains a key for the object that is assigned to a null literal. Here is a short repro of this behavior: https://gist.github.com/mnebes/12e51348d76440c5106202315494272a
I think one could fix that by slightly reordering the decodeMaybeNull
function to first check for the null literal and only after that invoke the decoder like so:
- let private decodeMaybeNull path (decoder : Decoder<'T>) value =
- // The decoder may be an option decoder so give it an opportunity to check null values
- match decoder path value with
- | Ok v -> Ok(Some v)
- | Error _ when Helpers.isNullValue value -> Ok None
- | Error er -> Error er
+ let private decodeMaybeNull path (decoder : Decoder<'T>) value =
+ // The decoder may be an option decoder so give it an opportunity to check null values
+ if Helpers.isNullValue value then
+ Ok None
+ else
+ match decoder path value with
+ | Ok v -> Ok(Some v)
+ | Error er -> Error er
This works, but judging by the comment this is on purpose that the decoder is executed (though I can't quite imagine a situation where that would be effectively different than "short-circuiting" here?), so if you have any advice as to how to proceed it would be highly appreciated!
#r "nuget: Thoth.Json.Net, 10.1.0"
open Thoth.Json.Net
let json =
"""
{
"x": 123,
"y": 456,
}
"""
match Decode.fromString Decode.value json with
| Ok _ ->
printfn "The JSON is valid"
| Error error ->
printfn $"The JSON is invalid: \n%s{error}"
The JSON is valid
This should not parse since the trailing comma is out of spec.
In order to make it easier to work with the tests,
the build.fsx
should be able to extract the info about the tests files from the paket.depencies
file.
It should allow us to know the path under paket-files
and also update the fsproj
file.
Perhaps it's possible to generate a Meta.fsproj
containing the Include
statement for the tests files and then import Meta.fsproj
in the Tests.fsproj
file.
Like that we can just "clean" the info generated by paket in Tests.fsproj
.
(moved from MangelMaxime/Thoth#133)
I have this enum:
[<StringEnum>]
type Camera = FirstPerson | ArcRotate | IsometricTopDown
When I serialize it on the server, it is serialized with UpperCase ("Camera":"FirstPerson"
).
Then on the client side it does not get recognized because Fable seems to expect lowerCase ("firstPerson"
).
Workaround 1:
I think in this case I can just remove the StringEnum
because that value is not/(no longer) passed to any ts/js
Workaround 2:
disable lowercasing with [<StringEnum(CaseRules.None)>]
Fix 1:
The encoder on the server could detect the presence of StringEnum
and check the case rules
Fix 2:
The decoder on the client could detect it and lowerCase the first char.
There doesn't seem to be any reflection info emitted for string enums, so either this would need to be extended in Fable, or fixed on the server side:
[<StringEnumAttribute>]
type MyStringEnum = A | B
type MyRecord = { I : int; E : MyStringEnum }
generates this reflection info:
export function MyRecord$reflection() {
return record("Test.MyRecord", [], MyRecord, () => [["I", int32], ["E", string]]);
}
Disclaimer: I don't know much about how nuspec
and nuget
package works. In general, they just work for me so I am fine. But with Thoth.Json.Net
I have a more complex package and I am a bit lost.
@forki this issue is about my call for help on Twitter. I tried to sum up the different problem I have and what actions have been taken when so you can have a global vision of the situation. Sorry for the long issue but I tried to be as explicit as possible.
Problem n°1: The dependencies list doesn't reflect the difference depending on the targetted framework.
Since several version Thoth.Json.Net
have the following depencies list:
Instead of something like that:
This problem appeared when I tried to lower Newtonsoft.Json
dependency to >= 11.0.2
instead of 12.0.1
.
At that time, I switched from dotnet pack
to paket pack
using paket.template
in project mode so it had the correct dependency for Newtonsoft.Json
based on paket.dependencies
.
In the past, @forki mentionned that if we didn't need different transitive deps in different framework it was "ok". Comment
However now, I need different deps depending on the Framework.
See how .NETStandard 2.0 require Fable.Core
now while .NETFramework 4.6 doesn't use it because Fable.Core
is not available here and was generating exceptions.
In order to archieved this result, I use paket.template
in file mode. Source
Problem n°2: It seems that even if we have Newtonsoft.Json >= 11.0.2
the dll was using/required 12.0.0
.
@bentayloruk raised an issue about that #18 and because I didn't see any problem with releasing a new version solving his problem we added lowest_matching:true
to paket.dependencies
Problem n°3: The AssemblyInfo
of version 3.5.0-beta-001
seems to say that the AssemblyVersion
is 1.0.0 which seems wrong.
I'm having some issues, but not sure why they are happening yet. Will investigate.
Side question, 3.5.0 beta 1 is
1.0.0.0
in all of the assembly version attributes. Is that intentional?
Originally posted by @bentayloruk in #19 (comment)
I suppose this is related to the changes I made when using paket.template
in file mode. When doing so because the file mode of paket was asking the same info that I already had in my fsproj
I removed them from that last file.
My question is should we keep the info in both file? Should I use FAKE to generate the AssymblyInfo
file and how can I use that generated file?
Problem n°4: Should we set an upper version restriction on the depencies?
As you can see here Newtonsoft.Json
is marked as >= 11.0.2
so people can use version 12+
of it.
While Fable.Core
is marked as (>= 3.0.0 && < 4.0.0)
. What is the correct way to restrict dependencies?
I'm trying to parse a json object where the properties come from two different systems which have different fields with different case.
Here is a sample
system1:
[ {"id": "39336bd7-ecdc-4755-ac21-8f852d70d311", "data": ["one", "two", "three", "four"], "userid": "user22", "deviceid": "device123", "timestamp": 2345} ]
system2:
[ {"id": "39336bd7-ecdc-4755-ac21-8f852d70d312", "data": ["one", "two" ], "userId": "user122", "deviceId": "device123", "timestamp": 2346} ]
Have a look at userId
and deviceId
Here is my decoder:
Decode.object
(fun get ->
{
Id = get.Required.Field "id" Decode.guid
Data = get.Required.Field "data" JObjectDecoder
DeviceId = get.Required.Field "deviceid" Decode.string
Timestamp = get.Required.Field "timestamp" Decode.int64
UserId = get.Required.Field "userid" Decode.string
}
)
How can I get it to support both cases?
I am trying to decode a mail message with email addresses from a json request.
Decoders are as follows:
open Thoth.Json.Net
open System.Net.Mail
/// Builds a System.Net.Mail.MailAddress from the json request.
let addressDecoder : Decoder<MailAddress> =
Decode.object
(fun get ->
let email = get.Required.Field "email" Decode.string
let display = get.Optional.Field "display" Decode.string |> Option.defaultValue email
new MailAddress(email, display) )
/// Builds a System.Net.Mail.MailMessage from the json request.
let requestDecoder : Decoder<MailMessage> =
Decode.object
(fun get ->
let msg = new MailMessage()
get.Required.Field "to" (Decode.list addressDecoder) |> List.iter msg.To.Add
get.Optional.Field "cc" (Decode.list addressDecoder) |> Option.defaultValue [] |> List.iter msg.CC.Add
msg.From <- get.Required.Field "from" addressDecoder
msg.Subject <- get.Required.Field "subject" Decode.string
msg.Body <- get.Required.Field "body" Decode.string
msg.IsBodyHtml <- get.Optional.Field "isBodyHtml" Decode.bool |> Option.defaultValue false
msg )
It works if I pass in a valid json string:
"""
{
"to": [ { "email": "[email protected]", "display": "Jordan Marr" } ],
"from": { "email": "[email protected]" },
"subject": "Test - optional fields",
"body": "Hello, world."
}
"""
|> Decode.fromString requestDecoder
However, if I leave out the required "from" email address, it fails with a null reference exception.
"""
{
"to": [ { "email": "[email protected]", "display": "Jordan Marr" } ],
"zzzzzfrom": { "email": "[email protected]" },
"subject": "Test - optional fields",
"body": "Hello, world."
}
"""
|> Decode.fromString requestDecoder
My expectation is that the decoder would safely return an Error Result saying that "from" is a required field.
Similarly, if I leave out the "to" field, it will fail with a null reference exception when I am expecting an Error Result.
I'd like to upgrade a Fable project from Fable 3 to Fable 4.
This package currently requires Fable.Core >= 3.1.6 and < 4.0. Which makes it not possible to upgrade to Fable 4.
I'm wondering the following:
Original issue: MangelMaxime/Thoth#142
by @dbrattli
Looks like Decode.string
fails with this string. Using Thoth.Json.Net (3.1) Newtonsoft.Json (12.0.1). Anyone that can repro this?
Decode.fromString Decode.string "\"2018-08-06T10:06:40.000\""
"Error at: `$` Expecting a string but instead got: "2018-08-06T10:06:40""
Probably because it's a datetime, perhaps related to https://stackoverflow.com/questions/11856694/json-net-disable-the-deserialization-on-datetime
Currently, Thoth encodes int64
as a string i.e:
(Encode.list [ Encode.int64 42L ] |> Encode.toString 0) = "[\"42\"]"
Which might not be what you expect, and most importantly it might not be what the receiver expect. Int64 allows values up to 9223372036854775807 while JSON safe numbers are up to 9007199254740991. JValue will accept Int64.MaxValue
, so not sure why we encode them as string? I would suggest that we encode int64
directly using JValue(value) :> JsonValue
and instead document that numbers above 9007199254740991 might be unsafe for the receiver? At least i think it's safer than sending strings by default, or?
How to reference both NuGet packages ?
My library should work on .NET and JS in the fsproj I have:
<ItemGroup Condition="$(DefineConstants.Contains('FABLE_COMPILER'))">
<PackageReference Include="Thoth.Json" Version="10.2.0" />
</ItemGroup>
<!-- a Not-Contains-Condition with leading exclamation mark: -->
<ItemGroup Condition="!$(DefineConstants.Contains('FABLE_COMPILER'))">
<PackageReference Include="Thoth.Json.Net" Version="11.0.0" />
</ItemGroup>
Is there another way to reference both packages?
then in the code :
#if FABLE_COMPILER
open Thoth.Json
#else
open Thoth.Json.Net
#endif
Encode.Auto.toString(..)
When compiled with Fable 4.14 fails with
The value, namespace, type or module 'Encode' is not defined. (code 39)
Issue by matthid
Thursday Oct 24, 2019 at 13:45 GMT
Originally opened as MangelMaxime/Thoth#175
open Fable.Core
open Thoth.Json.Net
[<StringEnum>]
type Test =
| Test1
| TEST2
[<EntryPoint>]
let main argv =
let t = TEST2
printfn "%A" t
let json = (Encode.Auto.toString(0, t))
printfn "json %A" json
let t2 : Test = Decode.Auto.unsafeFromString(json)
printfn "res %A" t2
0 // return an integer exit code
I can see the #16 was closed like this:
@MangelMaxime wrote:
I don't see any problem with using string to represent int64 in JSON.
Our data provider requires us to send:
{
"command": "getTickPrices",
"arguments": {
"timestamp": 1637589093796
}
}
1637589093796
is out of range for int
, so how am I to create a valid JSON request? They won't accept "1637589093796"
. This default behavior is a trouble, how to work it around?
Hi,
I may be misunderstanding Decode.fromString
, but the implementation and its unsafe counterpart seems to suggest that fromString
should not throw, ever. However, I am able to get it to throw by giving it some bad data:
System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'
This exception was originally thrown at this call stack:
Thoth.Json.Net.Decode.makeUnion(Microsoft.FSharp.Collections.FSharpMap<string, Microsoft.FSharp.Core.FSharpRef<Thoth.Json.Net.BoxedDecoder>>, bool, System.Type, string, string, Newtonsoft.Json.Linq.JToken[])
[email protected](string, Newtonsoft.Json.Linq.JToken)
Thoth.Json.Net.Decode.DecoderCrate<T>.Decode(string, Newtonsoft.Json.Linq.JToken)
Thoth.Json.Net.Decode.AutoModule.generateDecoder@1289<T>.Invoke(string, Newtonsoft.Json.Linq.JToken)
Thoth.Json.Net.Decode.fromValue<T>(string, Microsoft.FSharp.Core.FSharpFunc<string, Microsoft.FSharp.Core.FSharpFunc<Newtonsoft.Json.Linq.JToken, Microsoft.FSharp.Core.FSharpResult<T, System.Tuple<string, Thoth.Json.Net.ErrorReason>>>>, Newtonsoft.Json.Linq.JToken)
Thoth.Json.Net.Decode.fromString<T>(Microsoft.FSharp.Core.FSharpFunc<string, Microsoft.FSharp.Core.FSharpFunc<Newtonsoft.Json.Linq.JToken, Microsoft.FSharp.Core.FSharpResult<T, System.Tuple<string, Thoth.Json.Net.ErrorReason>>>>, string)
All I did to reproduce this is leave off a leading [
from my input string, which is being decoded into a single case DU. Is this a bug in Thoth, or something I'm doing wrong? Obviously I can simply catch this or all exceptions and assume the decoding failed, but I'm wondering why I need to do that when fromString
already returns a Result<>
.
Original issue: MangelMaxime/Thoth#141
by @brase
I was migrating my fable 1 project to fable 3. So I hat to change the serialization part from Fable.JsonConverter to Thoth.Json.
Nearly everything works but there is one record which causes a stack overflow during encoding:
i.e.
type MyRecType = { Name: string Children: MyRecType List }I put everything together in a sample repo:
https://github.com/brase/thothrex
I use thoth.json.net as the default json encoder, because that's how the safe template was structured:
https://github.com/SAFE-Stack/SAFE-BookStore/blob/master/src/Server/Program.fs#L45
With 2.5, everything worked fine.
Now I've updated to 3.0, and have two issues:
In both cases, the error message is Cannot generate auto encoder for MyType. Please pass an extra encoder.
For 1), this only kinda accidentally uses Thoth because it's registered as the default, it is actually used for an web api that is consumed by a C# client, and not for fable interop.
What is your opinion on this?
Is registering thoth as the default asp.net core serializer actually a good idea, or should I change this back to newtonsoft?
And for 2, would you be open to fixing this so it supports interface options
, as long as they are None
?
Reposting this issue here as originally submitted in the old Issues repos.
Hi Thothers!
I've tried to figure this out, but failed, so hoping someone in here will have the knowledge.
I have a problem which I think stems from the fact that the Thoth.Json.Net
nuspec specifies <dependency id="Newtonsoft.Json" version="11.0.2" />
but the nupkg/lib/netstandard2.0/Thoth.Json.Net.dll
references version 12.0.0.0
.
And here is the lib reference (via ILSpy):
In our case, Thoth.Json.Net
is a dependency of our first assembly A and then we reference A from our second assembly B. We then reference assembly B from a web project, where the dependencies are managed by Nuget, not Paket. In this situation, Thoth.Json.Net
is a transitive dependency of our web application and as a result, so is Newtonsoft.Json
. Nuget correctly identifies this, reads the nuspec for Thoth and based on that decides we are fine with version 11.0.2
of Newtonsoft.Json
(I think Nuget defaults to the earliest version of the dependency?). However, at runtime our web application fails because Thoth.Json.Net
tries to load version 12.0.0.0
.
I've done a bunch of Googling, but have been unable to determine how I'm supposed to handle this in the .NET Core world (in the old world I might have tried a "downgrade" assembly binding). On the surface it would seem sensible to me that the lib distribution of Thoth.Json.Net
should reference the minimum version of it's dependencies in order to avoid this, but maybe I'm missing something and this is a scenario that should be fine? If so, does anyone know the incantations I need to mumble?
I'm currently working around this by adding version 12 of Newtonsoft as a top level PackageReference in my web project, but that is not ideal.
Issue by theimowski
Wednesday Mar 06, 2019 at 12:00 GMT
Originally opened as MangelMaxime/Thoth#131
I have an app using net40 and would like to use Thoth.Json for serialisation.
Currently the project supports net46 - do you think it would be reasonable to add support for net40 as well?
That would be very helpful
Hello!
I think I have figured out how to implement an Auto decoder for seq<'t>
:
open System
open System.Collections
open System.Collections.Generic
type private UnboxedSeq<'t> (inner : obj seq) =
interface seq<'t> with
member this.GetEnumerator() : IEnumerator<'t> =
(seq {
for x in inner do
yield x :?> 't
}).GetEnumerator()
member this.GetEnumerator() =
(this :> seq<'t>).GetEnumerator() :> IEnumerator
let private genericSeq (elementT : Type) (decoder: BoxedDecoder) =
let unboxedSeqT = typedefof<UnboxedSeq<_>>
let seqT = unboxedSeqT.MakeGenericType(elementT)
fun (path : string) (value: JsonValue) ->
if not (Helpers.isArray value) then
(path, BadPrimitive ("a seq", value)) |> Error
else
let values = value.Value<JArray>()
(values, Ok []) ||> Seq.foldBack (fun value acc ->
match acc with
| Error _ -> acc
| Ok acc ->
match decoder.Decode(path, value) with
| Error er -> Error er
| Ok result -> result :: acc |> Ok)
|> Result.map (fun xs -> Activator.CreateInstance(seqT, xs))
However, I'm not sure how to contribute it.
Should I add tests to this repo first?
This code throws System.ArgumentException: 'Could not determine JSON object type for type Program+MyRecord.'
type MyRecord = {
Field1 : string
Field2 : int
Field3 : bool
}
type Wrapper<'a> = {
Id: string
Config: 'a
}
let myObject = {
Id = "test test test";
Config = (box {Field1 = "hi"; Field2 = 2; Field3 = true })
}
let result = JsonConvert.SerializeObject(myObject, Converters.Converter())
If we remove the box
, the serialization works but sadly in my case I cannot avoid it.
Whenever I use Decode.fromString
, I expect it to return either Ok
or Error
and never throw exceptions.
However, if the JSON contains a really large number, a System.InvalidCastException
exception is thrown.
The various int decoders do have bounds checking, and that works to some extent. But if the number is too crazy large, even the bounds check don’t help.
If this is a problem with how Newtonsoft does things, maybe add a try-with
in Thoth.Json.Net?
❯ dotnet fsi
Microsoft (R) F# Interactive version 12.7.0.0 for F# 7.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
For help type #help;;
> #r "nuget: Thoth.Json.Net, 11.0.0";;
[Loading /Users/simon/.packagemanagement/nuget/Cache/2fd0b2ac9e4082b4ba06da12786fc9dc357957f471b12f92af911c26d54f0284.fsx]
module FSI_0002.
2fd0b2ac9e4082b4ba06da12786fc9dc357957f471b12f92af911c26d54f0284
> open Thoth.Json.Net;;
-- int fails:
> Decode.fromString Decode.int "9999999999999999999";;
System.InvalidCastException: Object must implement IConvertible.
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at Newtonsoft.Json.Linq.Extensions.Convert[T,U](T token)
at Newtonsoft.Json.Linq.Extensions.Value[T,U](IEnumerable`1 value)
at Newtonsoft.Json.Linq.Extensions.Value[U](IEnumerable`1 value)
at [email protected](String path, JToken value)
at Thoth.Json.Net.Decode.fromValue[T](String path, FSharpFunc`2 decoder, JToken value)
at Thoth.Json.Net.Decode.fromString[T](FSharpFunc`2 decoder, String value)
at <StartupCode$FSI_0004>.$FSI_0004.main@() in /Users/simon/tmp/stdin:line 4
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
Stopped due to error
-- Let’s try int64 instead. Also fails:
> Decode.fromString Decode.int64 "9999999999999999999";;
System.InvalidCastException: Object must implement IConvertible.
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at Newtonsoft.Json.Linq.Extensions.Convert[T,U](T token)
at Newtonsoft.Json.Linq.Extensions.Value[T,U](IEnumerable`1 value)
at Newtonsoft.Json.Linq.Extensions.Value[U](IEnumerable`1 value)
at [email protected](String path, JToken value)
at Thoth.Json.Net.Decode.fromValue[T](String path, FSharpFunc`2 decoder, JToken value)
at Thoth.Json.Net.Decode.fromString[T](FSharpFunc`2 decoder, String value)
at <StartupCode$FSI_0005>.$FSI_0005.main@() in /Users/simon/tmp/stdin:line 5
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
Stopped due to error
-- Removing one `9`, it’s a valid in64:
> Decode.fromString Decode.int64 "999999999999999999";;
val it: Result<int64,string> = Ok 1000000000000000000L
-- And then, when using just int the bounds check works:
> Decode.fromString Decode.int "999999999999999999";;
val it: Result<int,string> =
Error
"Error at: `$`
Expecting an int but instead got: 999999999999999999
Reason: Value was either too large or too small for an int"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.