【问题标题】:JSON deserialization: input DateTime? to output Option<DateTime>JSON反序列化:输入日期时间?输出 Option<DateTime>
【发布时间】:2021-11-20 13:50:13
【问题描述】:

上下文:

一种类型有两种表示形式:一种在 C# 中,另一种在 F# 中。 C#类型的值被序列化为json,然后反序列化为F#类型的值。

有没有直接的方法将null json 属性转换为Option&lt;&gt; F# 值?

我正面临这样一种情况:null C# DateTime? UpdatedDate 属性被序列化为 json,然后预计会被反序列化为 FSharpOption&lt;DateTime&gt; UpdatedDate 值(F# 类型、C# 代码、长篇故事......)代码。

我的 json 看起来像这样:

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

从技术上讲,我可以将我的 json 反序列化为包含 DateTime? UpdatedDate 的 C# 类型,然后将结果值映射到包含 FSharpOption&lt;DateTime&gt; UpdatedDate 的 F# 类型,但肯定有更好的方法...


编辑:

为了反序列化 json,我使用 Newtonsoft 的 JsonConvert.DeserializeObject 和 .NET 5 + C# 9。

【问题讨论】:

  • 您使用的是哪个 JSON 序列化库?如果是 Newtonsoft,那么 Newtonsoft.Json.FSharp 会为您所描述的内容提供支持。
  • @brianberns 啊,应该提到,对不起。我正在使用 Newtonsoft 的 JsonConvert.DeserializeObject
  • github.com/jet/FsCodec 有一个 FsCodec.NewtonsoftJson,其中包含一个用于 Newtonsoft 的 OptionConverter,它可以干净地处理 FSharpOptions 对于 STJ,v5 可以正确处理它们 OOTB(以前的 FsCodec.SystemTextJson 有一个JsonOptionConverter 通用,不需要你跳过的箍(但只使用 STJ 5.0 库是真正的答案))
  • 谢谢@RubenBartelink 我一定会检查的。

标签: c# json f# option fsharpoption


【解决方案1】:

Newtonsoft.Json.FSharp 包中的OptionConverter 可以为您处理这个问题。您的代码将如下所示:

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

【讨论】:

【解决方案2】:

好的,感谢@brianberns 分享的示例,我明白了。示例代码:

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("");
}

用法:

var serializerOptions = new JsonSerializerOptions();

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

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

唯一需要注意的是,我将 Newtonsoft 序列化程序替换为 System.Text.Json 序列化程序 (JsonSerializer)。


编辑:

按照@ruben-bartelink 的建议,我使用了建议的 nuget (FsCodec.NewtonsoftJson) 而不是我自己的自定义转换器。现在代码要简单得多,因为我不必担心编写自己的转换。此外,我不必切换到System.Text.Json

var jsonSerializerSettings = new JsonSerializerSettings();

jsonSerializerSettings.Converters.Add(new OptionConverter());

var whoisResponses = JsonConvert.DeserializeObject<SharedSupport.Models.Whois.WhoisResponseV2[]>(
    snsMessage.Message,
    jsonSerializerSettings);

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 2020-01-03
相关资源
最近更新 更多