EDIT 2016-12-05: This was recognized as a bug and fixed: Readonly property corrupts normal property object references. #486
Original post:
I'm just starting out with Json.NET, but have encountered some strange behavior that seems like a bug.
If the Deserializer encounters an object reference ("$ref": "2") that was originally defined in a readonly property (get; only), it fails to deserialize and returns null instead.
Class
public class Parent
{
public Child ReadOnlyChild
{
get
{
return Child;
}
}
public Child Child {get; set;}
}
public class Child
{
}
Serialization:
Parent p = new Parent() { Child = new Child() };
JsonConvert.SerializeObject(p, new JsonSerializerSettings()
{ Formatting = Formatting.Indented,
PreserveReferencesHandling = PreserveReferencesHandling.Objects });
Serialized:
{
"$id": "1",
"ReadOnlyChild": {
"$id": "2",
},
"Child": {
"$ref": "2"
}
}
Deserialized (& reserialized to show the change):
{
"$id": "1",
"ReadOnlyChild": null,
"Child": null
}
Is this expected behavior, a bug, or am I missing something?
Note that sometimes [JsonProperty(Order = #)] is needed to force the serializer to act on ReadOnlyChild first. Regardless, the above Serialized JSON block will fail to deserialize properly, even if the class has been modified to deserialize Child first.
EDIT: The Child property being nulled is my concern, not ReadOnlyChild being somehow assigned a value by Json.NET
Thanks!
ReadOnlyChild, you're ordinaryChildproperty is referencing that id, and upon deserialization, since it can't restoreReadOnlyChild, the whole reference tracking business get's all f'ed up.ReadOnlyChild, tries to place it inside that property -- fails, because it's not writable -- and ultimately leaves a reference (in its internal model) that the value for id"2"is now contained insideReadOnlyChild(which has no value since the assignment failed). It then gets to theChild's value,"$ref": "2", tries to resolve it as the value ofReadOnlyChild, and sets its value tonullas well.