我有一个历史记录列表,我们可以从第3方软件中检索。此列表可以为null或非空。
在C#中,我会这样写,因为list可以为null:
List<HistoryEntry>
但是我在用F#编写时很费力。我已经尝试过:
* Nullable<HistoryEntry list>
* HistoryEntry list option
* HistoryEntry list?
* HistoryEntry list | null
但是,这些都不起作用。我们使用一个ListConverter,它几乎在所有地方都使用过,而且我不敢更改它(因为这会破坏所有内容):
type ListConverter() =
inherit JsonConverter()
override __.CanConvert(t : Type) = (t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<list<_>>)
override __.WriteJson(writer, value, serializer) =
let list = value :?> System.Collections.IEnumerable |> Seq.cast
serializer.Serialize(writer, list)
override __.ReadJson(reader, t, _, serializer) =
let itemType = t.GetGenericArguments().[0]
let collectionType = typedefof<IEnumerable<_>>.MakeGenericType(itemType)
let collection = serializer.Deserialize(reader, collectionType) :?> IEnumerable<_>
let listType = typedefof<list<_>>.MakeGenericType(itemType)
let cases = FSharpType.GetUnionCases(listType)
let rec make =
function
| [] -> FSharpValue.MakeUnion(cases.[0], [||])
| head :: tail ->
FSharpValue.MakeUnion(cases.[1],
[| head
(make tail) |])
make (collection |> Seq.toList)
我的问题是:如何创建该序列化程序可以理解的可空列表?
答案 0 :(得分:2)
我实际上认为问题出在ListConverter,而不是您要使用的列表类型。 ListConverter不能说明整个集合为null,这在JSON中是完全有可能的。我认为最简单的更改是使用Seq.toList
的自定义版本,该版本检查空值并将其转换为空列表。
let toJsonList s =
if s |> box |> isNull
then []
else s |> Seq.toList
然后将ListConverter的最后一行更改为:
make (collection |> toJsonList)