Home > other >  JSON deserialization: input DateTime? to output Option<DateTime>
JSON deserialization: input DateTime? to output Option<DateTime>

Time:09-29

Context:

one type has two representations: one in C# and one in F#. Value of the C# type gets serialized to json and then deserialized into a value of the F# type.

Is there a straightforward way to convert null json properties to Option<> F# values?

I'm facing a situation where null C# DateTime? UpdatedDate property gets serialized to json and then is expected to be deserialized into an FSharpOption<DateTime> UpdatedDate value (F# type, C# code, long story...) which breaks the code.

My json looks like this:

{
  "Property1": "1",
  "UpdatedDate": null,
  "Property2": "2"
}

I technically could deserialize my json to the C# type containing DateTime? UpdatedDate and then map the resulting value to the F# type containing FSharpOption<DateTime> UpdatedDate, but surely there must be a better way...


EDIT:

To deserialize json I'm using Newtonsoft's JsonConvert.DeserializeObject and .NET 5 C# 9.

CodePudding user response:

OptionConverter in the Newtonsoft.Json.FSharp package can handle this for you. Your code will look something like this:

let records =
    JsonConvert.DeserializeObject<MyType[]>(
       json,
       [| OptionConverter() :> JsonConverter |])

CodePudding user response:

Ok, I figured it out thanks to the example @brianberns shared. Sample code:

public class DummyJsonConverter : JsonConverter<FSharpOption<DateTime>>
{
    public override FSharpOption<DateTime> Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options) =>
        FSharpOption<DateTime>.None;

    public override void Write(
        Utf8JsonWriter writer,
        FSharpOption<DateTime> dateTimeValue,
        JsonSerializerOptions options) =>
        writer.WriteStringValue("");
}

Usage:

var serializerOptions = new JsonSerializerOptions();

serializerOptions.Converters.Add(new DummyJsonConverter());

var whoisResponses = JsonSerializer.Deserialize<SharedSupport.Models.Whois.WhoisResponseV2[]>(
    snsMessage.Message,
    serializerOptions);

The only caveat is that I replaced the Newtonsoft serializer with the System.Text.Json serializer (JsonSerializer).

  • Related