Simple strong typing of whether JSON properties are excluded or null
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.paket
src
.editorconfig
.gitattributes
.gitignore
CONTRIBUTING.md
LICENSE
README.md
RELEASE_NOTES.md
appveyor.yml
paket.dependencies
paket.lock

README.md

FSharp.JsonSkippable

NuGet Build status

JsonSkippable is an F# library for use with Newtonsoft.Json that allows you to easily differentiate between null and omitted JSON properties in a simple and strongly typed manner, for both serialization and deserialization.

For optimal effect, use it together with a library that allows you to serialize option as null, such as Microsoft.FSharpLu.Json. You can also use FSharp.JsonSkippable on its own just to control the presence of properties when serializing and deserializing.

TL;DR

This library defines the following type:

type Skippable<'T> =
  | Skip
  | Include of 'T

as well as a module with helper methods (Skippable.map, Skippable.bind, etc.) and a Newtonsoft.Json ContractResolver that manages the serialization and deserialization of the Skippable type.

You can define your serializable types like this to have full control of whether to include or exclude properties:

type Example =
  { A: int option Skippable
    B: bool option Skippable }

Example

// Where you set up serialization

open Newtonsoft.Json

let settings =
  JsonSerializerSettings(
    ContractResolver = 
      FSharp.JsonSkippable.Serialization.SkippableContractResolver()
    )
settings.Converters.Add(Microsoft.FSharpLu.Json.CompactUnionJsonConverter())
let serialize x = JsonConvert.SerializeObject(x, settings)
let deserialize<'a> x = JsonConvert.DeserializeObject<'a>(x, settings)


// Where you define and use your types

open FSharp.JsonSkippable

[<CLIMutable>]
type Example =
  { A: int option Skippable
    B: bool option Skippable }
    
    
// Example of serialization
    
let x1 = { A = Include (Some 2); B = Include (Some true) }
let x1s = serialize x1  // {"A":2,"B":true}

let x2 = { A = Include None; B = Skip }
let x2s = serialize x2  // {"A":null}


// Example of deserialization

let x1' = deserialize<Example> x1s
x1' = x1  // true

let x2' = deserialize<Example> x2s
x2' = x2  // true


// You can then pattern match on the members like you'd expect
match x1'.A with
| Include (Some i) -> ...  // A was an int
| Include None -> ...  // A was null
| Skip -> ...  // A was not present