I noticed some strange output from Newtonsoft.Json today, I'm not sure if it is an interaction with F# types or something that can occur in C# as well, so I've tagged both. I have a list of the following record being serialized:
type SplitTracker =
{
[<JsonIgnore>]
split : SplitDefinition
mutable start : duration
mutable ``end`` : duration
mutable lapCount : int
mutable duration : duration Option
}
I serialize it with JsonConvert.SerializeObject
and I get the following odd output:
"splits": [
{
"start@": "0.00",
"end@": "0.00",
"lapCount@": 0,
"duration@": null,
"start": "0.00",
"end": "0.00",
"lapCount": 0,
"duration": null
},
{
"start@": "0.00",
"end@": "0.00",
"lapCount@": 0,
"duration@": null,
"start": "0.00",
"end": "0.00",
"lapCount": 0,
"duration": null
}
Anyone know why that might be happening? The data is correct, the duplication of fields with the "@" symbol is the issue.
Private and protected members are not serialized.
Converts an Enum to and from its name string value. Newtonsoft.Json. JsonConverter. Newtonsoft.Json.Converters.
[JsonExtensionData] allows you to do is to serialize elements of a JSON document which does not have matching properties on the destination object to the dictionary which is decorated with the [JsonExtensionData] attribute.
JsonObjectAttribute(String) Initializes a new instance of the JsonObjectAttribute class with the specified container Id. JsonObjectAttribute(MemberSerialization) Initializes a new instance of the JsonObjectAttribute class with the specified member serialization.
The way you have defined your record is the culprit here. Record fields are exposed as properties - but you are using mutable properties. F# will turn that into a class that has fields for each of your mutables (the name is the property name, prefixed with @), and properties that read out those.
Json will now attempt to serialize all fields and all properties - hence you get the duplication.
Try it out in F# interactive:
type SplitTracker =
{
mutable start : float
}
let t = typeof<SplitTracker>
let fields1 = t.GetFields() // This will give you a field '@start'
let props1 = t.GetProperties() // This will give you a property 'start'
Contrast that with what you get when using a plain record:
type SplitTracker2 =
{
start : float
}
let t2 = typeof<SplitTracker2>
let fields2 = t2.GetFields() // You will not see any fields
let props2 = t2.GetProperties() // There is a single property 'start'
This should serialize correctly. Apart from that, it makes your code more idiomatic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With