self referencing loop exception with [JsonObject(IsReference = true)]


During some tests with RavenDb I receive a JsonSerializationException during the serialization of my object. The error is:
{"Self referencing loop detected for type
The class that I try to save is the following:
[JsonObject( IsReference = true )]
public class Category
    public Guid Id { get; set; }
    public string Name { get; set; }
    public Category Parent { get; set; }
    public IList<Category> Children { get; set; }
    public Category()
        : base()
        Children = new List<Category>();
    public void Add( Category category )
        category.Parent = this;
        Children.Add( category );
    public override Boolean Equals( Object obj )
        return true;
I have added the JsonObject attribute in order to avoid self reference
error. The problem arise when I override the Equals method and
returing always true.
Of course this is a unreal implementation, but I have a project where
the same error arise.
Closed May 27, 2012 at 7:37 AM by JamesNK
Using reference doesn't work for structs. Also it can't change because it would be a breaking change. You'll either have change Equals or set references to be serialized.


aparata wrote May 22, 2012 at 2:10 PM

After a little of digging in the code seems that the problem is in JsonSerializerInternalWriter at row 226. The code is:

if (_serializeStack.IndexOf(value) != -1)
{ ... }

if the 'value' object override the Equals method in a not conventional way (as in my example) the condition may assume a true value when instead it should be false.

A possible solution can be to substitute the code with something similar to the following:

if (_serializeStack.Any( o => Object.ReferenceEquals( o, value) ) )
{ ... }

wrote May 27, 2012 at 7:37 AM

aparata wrote May 27, 2012 at 10:51 AM

Thanks James for the answer.

Just one last question,

unfortunately I cannot change the entities in the domain.

I understand that with Struct value my change doesn't work, but do you think is acceptable to have in our code base (of course with a more elegant code) a solution like this?

if (value.GetType().IsValueType ? _serializeStack.IndexOf(value) != -1 : _serializeStack.Any( o => Object.ReferenceEquals( o, value) ))

What kind of problems can we have (you have talking about a breaking change)?

JamesNK wrote May 27, 2012 at 9:29 PM

Getting the type like that will hurt performance. That check is made for every deserialized object.

If you want reference loops serialized then set them to serialize instead of erroring.

wrote Feb 22, 2013 at 1:48 AM

wrote May 16, 2013 at 12:37 PM