thoth-org / Thoth.Json

Library for working with JSON in a type safe manner, this libs is targeting Fable

Home Page:https://thoth-org.github.io/Thoth.Json/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Calling Encode.Auto.toString throws System.Exception JS only

WallaceKelly opened this issue · comments

Am I doing something wrong? Or is this a bug?

Steps to Reproduce

  1. Run dotnet new console --language F#
  2. Run dotnet add package Thoth.Json
  3. Edit Program.fs as shown below.
  4. Run dotnet run

Project file

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RootNamespace>thoth_test</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Program.fs" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Thoth.Json" Version="7.0.0" />
  </ItemGroup>

</Project>

Program.fs

[<CLIMutable>]
type MyRecord = { Name: string; Age: int }
let myRecord = { Name = "Wallace"; Age = 42 }
let json = Thoth.Json.Encode.Auto.toString(0, myRecord)
printfn $"{json}"

Expected Result

Successfully prints a JSON version of my record value.

Actual Result

Unhandled exception. System.Exception: JS only
   at Fable.Core.JsInterop.op_BangBang[a,T](a x)
   at Thoth.Json.Encode.mapping@1-1(CaseStrategy caseStrategy, Boolean skipNullField, FSharpMap`2 extra, PropertyInfo fi)
   at Thoth.Json.Encode.autoEncodeRecordsAndUnions(FSharpMap`2 extra, CaseStrategy caseStrategy, Boolean skipNullField, Type t)
   at Thoth.Json.Encode.autoEncoder(FSharpMap`2 extra, CaseStrategy caseStrategy, Boolean skipNullField, Type t)
   at <StartupCode$thoth-test>.$Program.main@() in C:\temp\thoth-test\Program.fs:line 10

System Info

Windows 10

> dotnet --list-sdks
3.1.416 [C:\Program Files\dotnet\sdk]
5.0.210 [C:\Program Files\dotnet\sdk]
5.0.402 [C:\Program Files\dotnet\sdk]
5.0.404 [C:\Program Files\dotnet\sdk]
6.0.101 [C:\Program Files\dotnet\sdk]

Hello @WallaceKelly,

You are trying to use run the Fable version of Thoth.Json against .NET.

If you want to use Thoth.Json API on .NET for now it is provided using another package called Thoth.Json.Net.

More info available here: https://thoth-org.github.io/Thoth.Json/documentation/concept/fable-and-dotnet-support.html

Thank you, @MangelMaxime. I should have figured that out on my own. 🙄

This works, of course:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Program.fs" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="thoth.json.net" Version="8.0.0" />
  </ItemGroup>

</Project>
[<CLIMutable>]
type MyRecord = { Name: string; Age: int }
let myRecord = { Name = "Wallace"; Age = 42 }
let json = Thoth.Json.Net.Encode.Auto.toString(0, myRecord)
printfn $"{json}"

Your welcome.

The error is not really explicit I will see if we can make it more explicit in Fable.

Having 2 packages depending on the runtime is not ideal, there are plan in the future to have a single package working everywhere. That should avoid similar problem in the future.

I was just burned by this for 20 mins. Even changing the message from "JS only" to "- you need Thoth.Json.Net for dotnet" would be a big help.

@daz10000 Thoth.Json is not the one generating the exception it done by Fable.Core package.

Looking at the definition of the function, the error message should be:

You've hit dummy code used for Fable bindings. This probably means you're compiling Fable code to .NET by mistake, please check.

The problem is that Thoth.Json requires Fable.Core >= 3.1.6 when the improved error message was introduced in 3.6.2.

I released a new version which force Fable.Core to be at least at version 3.6.2.

Thanks for the quick reply, and that all makes sense. For what it's worth, I wasn't anywhere near Fable at the time (didn't suspect I was accidentally using a Fable library). That's what made it so confusing. This ticket was the only clue to error message. I was troubleshooting some Thoth encoding in fsi with something like this

#r "nuget:Thoth.Json"

open Thoth.Json
let v = 123
let s : string = Encode.Auto.toString v

I see the new error message now! I still think it's slightly misleading. I'm not compiling fable code to .net - I'm binding .net code to a fable library by accident. That might be a subtle distinction, but Thoth.Json doesn't scream Fable library .. I have no fable in this particular project so brain didn't even go there.

System.Exception: You've hit dummy code used for Fable bindings. This probably means you're compiling Fable code to .NET by mistake, please check.
   at Fable.Core.JsInterop.op_BangBang[a,T](a x)
   at <StartupCode$FSI_0002>.$FSI_0002.main@() in C:\XXX\t.fsx: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

The way I see to improve this error would be to do a try / catch and then check the error message in order to rewrite it.

But I don't think that a great solution. The elegant solution will come with Thoth.Json 11+ which is a rewrite of the library to support both Fable and .NET at the same time. So people will not have to worry about such things anymore in the future.