Skip to content

Instantly share code, notes, and snippets.

@whitebear-gh
Last active May 15, 2018 08:44
Show Gist options
  • Save whitebear-gh/f2a107961c5024ba61d032976292431a to your computer and use it in GitHub Desktop.
Save whitebear-gh/f2a107961c5024ba61d032976292431a to your computer and use it in GitHub Desktop.
Giraffe - Custom json serializer - require all properties except optional
open Newtonsoft.Json
open Newtonsoft.Json.Converters
module Json =
// Custom Json serialization / deserialization settings to be applied for the whole backend
let serializationSettingsEx =
let settings = JsonSerializerSettings()
settings.Converters.Add(OptionConverter())
let stringEnumConverter = StringEnumConverter()
stringEnumConverter.CamelCaseText <- true
settings.Converters.Add(stringEnumConverter)
settings.ContractResolver <- RequireObjectPropertiesContractResolver()
settings
let deserializeTo<'T> str =
JsonConvert.DeserializeObject<'T>(str, serializationSettingsTx)
let jsonEx<'a when 'a: equality> (data: 'a) = customJson serializationSettingsEx data
let bindJsonAsyncEx<'T> (ctx:HttpContext) = ctx.BindJsonAsync<'T>(serializationSettingsEx)
open System
open Microsoft.FSharp.Reflection
open Newtonsoft.Json
type OptionConverter() =
inherit JsonConverter()
override x.CanConvert (t) =
let canConv = t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<option<_>>
canConv
override x.WriteJson(writer, value, serializer) =
let value =
if value = null then null
else
let _,fields = FSharpValue.GetUnionFields(value, value.GetType())
fields.[0]
serializer.Serialize(writer, value)
override x.ReadJson(reader, t, existingValue, serializer) =
let innerType = t.GetGenericArguments().[0]
let innerType =
if innerType.IsValueType then (typedefof<Nullable<_>>).MakeGenericType([|innerType|])
else innerType
let value = serializer.Deserialize(reader, innerType)
let cases = FSharpType.GetUnionCases(t)
if value = null then FSharpValue.MakeUnion(cases.[0], [||])
else FSharpValue.MakeUnion(cases.[1], [|value|])
open System
open Newtonsoft.Json
open Newtonsoft.Json.Serialization
open System.Reflection
type RequireObjectPropertiesContractResolver() =
inherit CamelCasePropertyNamesContractResolver()
override x.CreateObjectContract(objectType : Type) =
let contract = base.CreateObjectContract(objectType)
contract.ItemRequired <- new System.Nullable<Required>(Required.Always);
contract
override x.CreateProperty(memberInfo : MemberInfo, memberSerialization : MemberSerialization) =
let jsonProperty = base.CreateProperty(memberInfo, memberSerialization);
// https://stackoverflow.com/questions/20696262/reflection-to-find-out-if-property-is-of-option-type
let isOption = jsonProperty.PropertyType.IsGenericType && jsonProperty.PropertyType.GetGenericTypeDefinition() = typedefof<Option<_>>
if isOption then (
jsonProperty.Required <- Required.Default
jsonProperty.NullValueHandling <- new System.Nullable<NullValueHandling>(NullValueHandling.Ignore)
)
jsonProperty
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment