F#: How to deserialize a private discriminated union with Newtonsoft.Json? - json

In his question and answer from 2018, Onur Gumus used [<JsonObject(MemberSerialization = MemberSerialization.Fields)>] to enable serialization/deserialization of a discriminated union with a private constructor.
For me, the serialization works as advertised, but deserialization produces this error: "Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type FSI_0037+Foo. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute."
Does anyone know how to get the deserialization working? I don't want to switch to a class type if it can be avoided. However, I've tried figuring out where to place a JsonConstructor attribute without any luck. I also tried passing a settings value with the ConstructorHandling value set to AllowNonPublicDefaultConstructor, but that changed nothing.
For convenience, I copy Onur's solution here:
open Newtonsoft.Json
[<JsonObject(MemberSerialization = MemberSerialization.Fields)>]
type Foo = private Bar of string
let f = Bar "f"
let s = JsonConvert.SerializeObject(f)
let f2 = JsonConvert.DeserializeObject<Foo>(s)
printf "%A" f2
In case it matters (since things seem to have changed since 2018), I'm using .NET 5.

I am reasonably sure you have stumbled onto a bug.
When I copied the sample code you refer to into LINQPad v6.13.13, and ran it, then it worked fine. I then tried to replace the attribute with another attribute - the one I mentioned in the comment. Not unexpectedly that didn't compile. So I just reverted to the original attribute. Then I got the same compile error you encountered. That should not have happened. It's a bug. But where?
Further investigation has revealed that the compile error is produced erroneously if I do the following in LINQPad:
Open the code snippet from a file, and try to run it. This compiles and runs fine.
Comment out the attribute, and try to run it. This produces the compile error in question. This is as it should be.
Bring back the attribute, and try to run it. This should compile and run fine of course, since the source is now as it was in step 1, but it still produces the compile error in question.
Trying the same steps repeatedly will produce the same problem, whether I restart LINQPad between runs or not.
Then I tried to reproduce the problem with Visual Studio. I did not succeed - there is no such problem in VS 16.10.3
I have no more time at the moment, but will continue to investigate later. I want to check this with the latest LINQPad beta.
As for your question, was this the cause?
UPDATE
I have now checked with LINQPad v6.14.10, the current beta version. The bug is not present there. I am not surprised. As I've mentioned in a comment, the compiler is my prime suspect. Even more so because you tell you have the problem in VSCode. But there is an even more interesting detail.
LINQPad has used a very old version of the F# compiler service for ages, because there was a bug that prevented updating it. Joseph Albahari, the creator of LINQPad, recently got impatient waiting for a fix for this bug, and found a workaround. That fix is only in the beta. The huge leap in the F# compiler service version naturally means lots of bugs has been fixed, and likely this one too.
I am not going to pursue this further. I don't use VSCode, but if this problem is present even in the latest REPL there, then maybe somebody should look into it.

Related

Devart LinqConnect for mysql A field initializer cannot reference the non-static field, method, or property

I couldn't solve this problem after linqConnect For Mysql generated entity of models for me. I thought devart is good software, without testing trial period, I purchased their license, but now I am facing this issue, I couldn't even get it working. please help
enter image description here
The the piece of code highlighted is "System.String.Empty", nothing is wrong here. A similar problem is discussed, for example, at Visual Studio 2015: Intellisense errors but solution compiles. Have you tried to build a project ignoring these fantom errors? Most likely, the build will succeed in this case. To avoid displaying such misleading "errors", choose "Build Only" droplist value (instead of "Build + IntelliSense") in the Error List window from your screenshot.

Razor exceptions

I have undoubtedly set something up wrong but frequently I get exceptions thrown by my Razor templates even though there is no problem with the templates. These are usually fixed by my doing a build.
If I do actually have an error in the template I get a popup asking me to debug in VS, but of course this does not actually allow me to debug the template.
Errors in my log are not all that helpful (see below).
Is it possible to both avoid spurious errors and get better information when there is actually a problem?
ServiceStack.Razor.Templating.TemplateCompilationException: Unable to compile template. Check the Errors list for details.
at ServiceStack.Razor.Templating.TemplateService.CreateTemplate(String template, Type modelType)
at ServiceStack.Razor.Templating.TemplateService.Compile(ViewPageRef viewPageRef, String template, Type modelType, String name)
at ServiceStack.Razor.Templating.TemplateService.Compile(ViewPageRef viewPageRef, String template, String name)
at ServiceStack.Razor.ViewPageRef.Compile(Boolean force)
I was having similar problems. I found the "easiest" way to find out what the error was, was to download all of service stack, build a debug version of the razor libary and link it into my project. I then set a break point in the ServiceStack.Razor.Templating.TemplateService.CreateTemplate method and was able to see the full exception details. From there I learnt that I had included an import in my razor page that was not referenced in my project.
Since I solved this it's been very reliable.
I had trouble with this myself, because ServiceStack swallowed the exceptions, and the logs, as you said, don't show the Errors collection. There are two ways to get that information:
Uncheck Enable Just My Code in the debugging options in Visual Studio (Debug -> Options and Settings). If you have checked Thrown for Common Language Runtime Exceptions in Debug -> Exceptions, you will get the exceptions, and be able to view the Errors collection.
A merge was committed some days ago to the ServiceStack repository, which makes it log the Errors collection. Demis Bellot apparently pushes new versions to NuGet fairly often, so it'll probably be there in a week or two.
I had the same problem. And my case, I have removed some libraries referenced in the project but the reference to them remained (eventhought I think removed it, but anyway) and this has been the problem.
After I deleted the references to libraries which don't exsits anymore in the project, it worked immediatelly.

Unexplainable ClassCastException thrown in Play Framework

I've been experiencing a strange error while working on my Play Framework project. While my project is running, I will sometimes receive a ClassCastException, but the error is this:
ClassCastException occured : models.Person cannot be cast to models.Person
This occurs usually when I'm calling a find method such as:
Person p = Person.find("name=?","Joe").first();
If I restart the project, the problem goes away, but only temporarily. It makes testing my project a major pain. How do I fix this?
I've experienced this error while in Dev mode in Play, in two scenarios (as far as I can remember):
Modify an entity and try to recover values from cache that are objects of that entity class.
A compilation error while reloading the code of the page/application
In both scenarios fixing compilation errors or cleaning the cache solved the issue.
Not saying that those are the only possibilities, it may be that you are having some other issue.
This most likely occurs because you've somehow loaded the Person class under two different class loaders. When a class is loaded twice in two different class loaders it's effectively two distinct classes.
(Unfortunately, I can't tell you where/how you might have done this.)
(And it is a bit curious to have the problem pop up on the statement you list. Are you certain that's where it's occurring? Perhaps you should show the exception traceback.)
In my case, this is related to applying evolutions from the web interface. Someone raised a bug for this, but so far it hasn't received any attention from the dev team. There is a patch attached to the ticket, but I haven't tried it, so YMMV.

Why am I getting a Stack underflow (error 1024) in release build?

I had this strange problem with stack underflow errors happen only in the release build of Flex Builder project. I looked around the web to find a solution, but while I found some related posts, nothing really helped my out. So here is this question and my solution in the answers so that it may hopefully help other people.
The Problem: I ported a java program (a game) to flex and it works fine in debug mode on Android, the web and Playbook. However, when I build a release version of the game, it crashes. The error reported is 1024, i.e. stack underflow, according to Adobe's documentation.
At first, I thought the problem was limited only to the Playbook, but no, the exact same problem happens at the exact same place on the web browser and Android. From the debugging information I inserted, I discovered that the exception appears to be thrown during the call to another function.
To solve the problem, I broke down the offending function in many individual functions and so narrowed down which precise part of the code what causing problem. This lead me to a few lines of code that had the following call (in a try-catch):
trace(e.getStackTrace())()
Hummm, this apparently was produced by the regex I used to refactor from Java to Actionscript. Removing the extra () solve the problem.
This is the kind of things I wished the compiler would catch instead of letting it fail only at release, when the function containing the offending code is pushed on the stack.

Inter-module exception name resolution through boost python does not work?

Here is my problem:
I have two C++ modules, A and B, which are built as dynamically-linked libraries. A offers basic math functions, and custom exception types. B is a higher level module that uses A.
B::someFunction() calls a function from A, and tries to catch custom exception A:MyExceptionFromA in order to convert it into a custom type B:MyExceptionFromB (since users of module B do not need to know about the implementation details of A).
Everything works fine as long as I remain in the C++ domain. However, if I expose B::someFunction() in python via boost python, the exception is not caught anymore in the C++ module.
I can catch std::runtime_error, from which A:MyExceptionFromA derives, and call typeid(e).name() to get the retrieve the correct mangled name, so I know the correct exception is thrown. Therefore I suspect that the problem comes from resolving this mangled symbol into the correct exception type.
I have found this link, which explains that "python uses [the insular] model to open extension modules, so that extension module writers don't need to know what symbols other extension modules might be using.". I'm suspecting this is part of the problem/solution, but I do not know enough about symbol resolution to figure out how to solve my problem.
Any ideas?
I found a work-around to my problem. Based on this and link text, I figured out that adding
import sys, dl
sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)
before my includes solves the problem, by forcing python to open libraries in immediate, global mode. But I'm still hoping for an alternative solution, if there's one. As mentioned in the first link, I'm suspicious that this could have unforeseen effects (I already know that name clashing could be a problem, and I suspect performance can be affected as well, but are there other side effects?)