Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save vasily-kirichenko/5520937 to your computer and use it in GitHub Desktop.
Save vasily-kirichenko/5520937 to your computer and use it in GitHub Desktop.
module NonNullListSerialization
open System
open System.IO
open System.Text
open Newtonsoft.Json
open FSharpx.Collections
open System.Collections.Generic
open Newtonsoft.Json.Serialization
open Newtonsoft.Json.Converters
open Microsoft.FSharp.Reflection
type NonEmptyListConverter() =
inherit JsonConverter()
override x.CanConvert(t:Type) =
t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<NonEmptyList<_>>
override x.WriteJson(writer, value, serializer) =
let list = value :?> System.Collections.IEnumerable |> Seq.cast
serializer.Serialize(writer, list)
override x.ReadJson(reader, t, _, serializer) =
let itemType = t.GetGenericArguments().[0]
let collectionType = typedefof<IEnumerable<_>>.MakeGenericType(itemType)
let collection = serializer.Deserialize(reader, collectionType) :?> System.Collections.IEnumerable |> Seq.cast
match collection |> Seq.toList with
| [] -> invalidOp "NonEmptyList cannot be empty"
| h :: t -> NonEmptyList.create h t :> _
let s = new JsonSerializer()
s.Converters.Add(new NonEmptyListConverter())
let serialize o =
use ms = new MemoryStream()
(use jsonWriter = new JsonTextWriter(new StreamWriter(ms))
s.Serialize(jsonWriter, o))
ms.ToArray()
let deserialize (t, data: byte array) =
use ms = new MemoryStream(data)
use jsonReader = new JsonTextReader(new StreamReader(ms))
s.Deserialize(jsonReader, t)
let twoWay o =
let bytes = serialize o
(o.GetType(), bytes) |> deserialize
// OK
let l = twoWay <| NonEmptyList.createParamsArray ("a", [|"b"; "c"|])
type Complex = { List: NonEmptyList<string> }
// System.ArgumentException: Object of type 'FSharpx.Collections.NonEmptyList`1[System.Object]' cannot be converted to type 'FSharpx.Collections.NonEmptyList`1[System.String]'.
let c = twoWay <| { List = NonEmptyList.createParamsArray ("a", [|"b"; "c"|]) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment