open System.Collections.Generic
open System.Runtime.Serialization.Formatters
open System.ComponentModel.DataAnnotations
open System.Globalization
open Microsoft.FSharp.Reflection
open Newtonsoft.Json.Linq
open Newtonsoft.Json.Converters
open Newtonsoft.Json.Serialization
type ParameterizedConstructorInitializingContractResolver() =
inherit DefaultContractResolver()
static member EmptyList<'T>() = List.empty<'T>
override __.CreatePropertyFromConstructorParameter(matchingMemberProperty : JsonProperty, parameterInfo : ParameterInfo) =
let property = base.CreatePropertyFromConstructorParameter(matchingMemberProperty, parameterInfo)
if (not (matchingMemberProperty = null) && property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() = typedefof<_ list>) then
let genericMethod = typeof<ParameterizedConstructorInitializingContractResolver>.GetMethod("EmptyList", BindingFlags.Public ||| BindingFlags.NonPublic ||| BindingFlags.Static)
let concreteMethod = genericMethod.MakeGenericMethod(property.PropertyType.GetGenericArguments())
let defaultValue = concreteMethod.Invoke(null, null)
property.DefaultValue <- defaultValue
property.DefaultValueHandling <- new System.Nullable<DefaultValueHandling>(DefaultValueHandling.Populate)
matchingMemberProperty.DefaultValue <- defaultValue
matchingMemberProperty.DefaultValueHandling <- new System.Nullable<DefaultValueHandling>(DefaultValueHandling.Populate)
printfn "\nDeserialization without ParameterizedConstructorInitializingContractResolver:"
JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "Missing SomeList"}""" ) |> printfn "%A"
JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "Populated SomeList", "SomeList" : ["a", "b", "c"]}""") |> printfn "%A"
printfn "\nDeserialization with ParameterizedConstructorInitializingContractResolver:"
let settings = JsonSerializerSettings(ContractResolver = new ParameterizedConstructorInitializingContractResolver())
let myrecord1 = JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "Missing SomeList"}""", settings )
let myrecord2 = JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "Populated SomeList", "SomeList" : ["a", "b", "c"]}""", settings )
let myrecord3 = JsonConvert.DeserializeObject<MyRecord>("""{ "Name": "null SomeList", "SomeList" : null}""", settings )
myrecord1 |> printfn "%A"
myrecord2 |> printfn "%A"
myrecord3 |> printfn "%A"
JsonConvert.SerializeObject(myrecord1, settings) |> printfn "Re-serialized myrecord1: %A"
JsonConvert.SerializeObject(myrecord2, settings) |> printfn "Re-serialized myrecord2: %A"
JsonConvert.SerializeObject(myrecord3, settings) |> printfn "Re-serialized myrecord3: %A"
if (System.Object.ReferenceEquals(myrecord1.SomeList, null)) then
raise (Exception("myrecord.SomeList = null"))
if (System.Object.ReferenceEquals(myrecord2.SomeList, null)) then
raise (Exception("myrecord.SomeList = null"))
if (System.Object.ReferenceEquals(myrecord3.SomeList, null)) then
raise (Exception("myrecord.SomeList = null"))
System.Object.ReferenceEquals(List.empty<string>, List.empty<string>) |> printfn "%A"