When using Newtonsoft for deserializing a JSON object in F#, I noticed that the deserialization process converts the missing integer fields to its default values. In the following example, the missing integer field in instanceB
is converted to an integer field with default value (0
). But when the missing field is Name
in instanceC
(which is of type string
), it converts to null
. Why is the output of deserialization different based on the type of the fields?
#r """Newtonsoft.Json.dll"""
open Newtonsoft.Json
type Test = {
Id: int
Name: string
}
let instanceA = """{"Id": 1, "Name": "A"}"""
let instanceB = """{"Name": "A"}"""
let instanceC = """{"Id": 1}"""
let A = JsonConvert.DeserializeObject<Test>(instanceA)
let B = JsonConvert.DeserializeObject<Test>(instanceB)
let C = JsonConvert.DeserializeObject<Test>(instanceC)
printfn "%A" A
printfn "%A" B
printfn "%A" C
Output:
val A : Test = { Id = 1
Name = "A" }
val B : Test = { Id = 0
Name = "A" }
val C : Test = { Id = 1
Name = null }
In .NET some types have null
as a possible value and some don't. The latter are called "value types", and the former are called "reference types".
int
is a value type, so it can't be null
.
string
is a reference type, so it can.
Every type does have a default value though. For reference types the default value is null
. For value types it depends on the type, but usually it's some variation of zero. So those are the values you're getting.