JSON反序列化:输入日期时间?输出选项<DateTime>
JSON deserialization: input DateTime? to output Option<DateTime>
上下文:
一种类型有两种表示形式:一种在 C# 中,一种在 F# 中。 C# 类型的值被序列化为 json,然后反序列化为 F# 类型的值。
是否有直接的方法将 null
json 属性转换为 Option<>
F# 值?
我面临这样一种情况,其中 null
C# DateTime? UpdatedDate
属性 被序列化为 json,然后预计将被反序列化为 FSharpOption<DateTime> UpdatedDate
破坏代码的值(F# 类型,C# 代码,长话短说...)。
我的 json 看起来像这样:
{
"Property1": "1",
"UpdatedDate": null,
"Property2": "2"
}
我在技术上可以将我的 json 反序列化为包含 DateTime? UpdatedDate
的 C# 类型,然后将结果值映射到包含 FSharpOption<DateTime> UpdatedDate
的 F# 类型,但肯定有更好的方法...
编辑:
要反序列化 json 我正在使用 Newtonsoft 的 JsonConvert.DeserializeObject
和 .NET 5 + C# 9。
Newtonsoft.Json.FSharp 包中的 OptionConverter
可以为您解决这个问题。您的代码将如下所示:
let records =
JsonConvert.DeserializeObject<MyType[]>(
json,
[| OptionConverter() :> JsonConverter |])
好的,感谢@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);
唯一需要注意的是,我用 System.Text.Json
序列化程序 (JsonSerializer
) 替换了 Newtonsoft 序列化程序。
编辑:
按照@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);
上下文:
一种类型有两种表示形式:一种在 C# 中,一种在 F# 中。 C# 类型的值被序列化为 json,然后反序列化为 F# 类型的值。
是否有直接的方法将 null
json 属性转换为 Option<>
F# 值?
我面临这样一种情况,其中 null
C# DateTime? UpdatedDate
属性 被序列化为 json,然后预计将被反序列化为 FSharpOption<DateTime> UpdatedDate
破坏代码的值(F# 类型,C# 代码,长话短说...)。
我的 json 看起来像这样:
{
"Property1": "1",
"UpdatedDate": null,
"Property2": "2"
}
我在技术上可以将我的 json 反序列化为包含 DateTime? UpdatedDate
的 C# 类型,然后将结果值映射到包含 FSharpOption<DateTime> UpdatedDate
的 F# 类型,但肯定有更好的方法...
编辑:
要反序列化 json 我正在使用 Newtonsoft 的 JsonConvert.DeserializeObject
和 .NET 5 + C# 9。
OptionConverter
可以为您解决这个问题。您的代码将如下所示:
let records =
JsonConvert.DeserializeObject<MyType[]>(
json,
[| OptionConverter() :> JsonConverter |])
好的,感谢@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);
唯一需要注意的是,我用 System.Text.Json
序列化程序 (JsonSerializer
) 替换了 Newtonsoft 序列化程序。
编辑:
按照@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);