Как создать обнуляемый список в F #? - PullRequest
0 голосов
/ 24 мая 2019

У меня есть список записей истории, которые мы получаем из стороннего программного обеспечения.Этот список может быть нулевым или не пустым.

В C # я написал бы это так, поскольку list может быть нулевым:

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)

Мой вопрос: как создать список, допускающий обнуление, который будет понят этому сериализатору?

1 Ответ

2 голосов
/ 24 мая 2019

Я действительно думаю, что проблема в ListConverter, а не в типе списка, который вы пытаетесь использовать. ListConverter не учитывает, что вся коллекция является нулевой, что вполне возможно в JSON. Я думаю, что самым простым изменением было бы использование пользовательской версии Seq.toList, которая проверяет наличие нулей и преобразует их в пустой список.

let toJsonList s =
   if s |> box |> isNull
   then []
   else s |> Seq.toList

Затем просто измените последнюю строку ListConverter на:

make (collection |> toJsonList)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...