Closed abelbraaksma closed 7 months ago
Reproduces on
module Testing
open System.Text.Json
open System.Text.Json.Serialization
type StringTrimJsonSerializer(o: JsonSerializerOptions) =
inherit JsonConverter<string>()
override this.Read(reader, _, _) =
match reader.TokenType with
| JsonTokenType.String -> reader.GetString().Trim()
| _ -> JsonException("Type is not a string") |> raise
override this.Write(writer, objectToWrite, options) = base.Write(writer, objectToWrite, options)
type SomeType = { Foo: string}
let serialize item =
let options = JsonSerializerOptions()
StringTrimJsonSerializer options |> options.Converters.Add
JsonSerializer.Serialize(item, options)
[<EntryPoint>]
let main _ =
{ Foo = "a" } |> serialize
0
Does not reproduce on:
module Testing
open System.Text.Json
open System.Text.Json.Serialization
type StringTrimJsonSerializer(o: JsonSerializerOptions) =
inherit JsonConverter<string>()
override this.Read(reader, _, _) =
match reader.TokenType with
| JsonTokenType.String -> reader.GetString().Trim()
| _ -> JsonException("Type is not a string") |> raise
override this.Write(writer, objectToWrite, options) = base.Write(writer, objectToWrite, options)
type SomeType = { Foo: int }
let serialize item =
let options = JsonSerializerOptions()
StringTrimJsonSerializer options |> options.Converters.Add
JsonSerializer.Serialize(item, options)
[<EntryPoint>]
let main _ =
{ Foo = 1 } |> serialize
0
Both release and debug
@vzarytovskii The latter never calls the StringTrimJsonSerializer.Write
method (there's no string in the type), so it makes sense that it doesn't fail. The JIT never has to emit the method, so you won't get the BadImageFormatException
.
The problem seems to be that base
here is an abstract class and the Write
method itself is also abstract
. In other words, it should never compile. If you try this with F# classes (abstract A, concrete B derives from A) then if B
uses base.Foo
it'll give a compile error saying that you cannot call an abstract method.
The same is true here, but for some reason, F# doesn't consider it an abstract method.
Using
base.XXX
to call a base method causes aBadImageFormatException
to be raised.EDIT: it looks like F# allowing me to call an abstract method, as the
base
class is abstract. This, I believe, should not be allowed and JIT therefore throws aBadImageFormatException
. If you try to write code in F# with anAbstractClass
and a derived class, you'd receive a normal compile-time error.Repro steps
The following code (requires Giraffe and FsUnit to run the test) throws a
BadImageFormatException
Expected behavior
Should call the base method or give compile error if such method doesn't exist.
Actual behavior
Throws:
Known workarounds
Don't use
base
in a derived method.Related information
On dotnet 6, using
System.Text.Json
serialization BCL classes, Windows 10/11.EDIT, the IL of the offending code looks as follows (Release build):