PassionateDeveloper
PassionateDeveloper

Reputation: 15138

JSON.Net Self referencing loop detected

I have a mssql database for my website within 4 tables.

When I use this:

public static string GetAllEventsForJSON()
{
    using (CyberDBDataContext db = new CyberDBDataContext())
    {
        return JsonConvert.SerializeObject((from a in db.Events where a.Active select a).ToList(), new JavaScriptDateTimeConverter());
    }
}

The code results in the following error:

Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'CyberUser' with type 'DAL.CyberUser'. Path '[0].EventRegistrations[0].CyberUser.UserLogs[0]'.

Upvotes: 222

Views: 251239

Answers (14)

Arul Jyothi
Arul Jyothi

Reputation: 1

JsonIgnoreAttribute attribute allows you to control which properties of your class get serialized into JSON format. By applying [JsonIgnore] directly above a property declaration, you instruct the serializer to skip that property during the process.

Upvotes: 0

Simon_Weaver
Simon_Weaver

Reputation: 145890

Make sure you aren't accidentally serializing a Task<T>

You can get this error if you forget to await an asynchronous method whose return value you intended to serialize.

    public async Task<JsonResult> GetTaxTable([FromServices] TaxService taxService)
    {
        var taxTable = /* await */ taxService.GetTaxTable();
        return new JsonResult(taxTable);
    }

In this example I had forgotten to await the GetTaxTable async method. So I inadvertently ended up passing a Task to the JsonResult constructor - and a Task isn't serializable. While it may at first look like everything blew up on you - the simple solution is to add await.

Upvotes: 5

birwin
birwin

Reputation: 2684

If you are like me and were previously calling SerializeObject with a converter, you will need to remove the converter parameter and add it to your config... Like so:

var isoConvert = new IsoDateTimeConverter();
isoConvert.DateTimeFormat = _dateFormat;
List<JsonConverter> converters = new List<JsonConverter>();
converters.Add(isoConvert);
JsonSerializerSettings settings = new JsonSerializerSettings()
{
    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    Converters = converters
};

// Old Code:
//response.Write(JsonConvert.SerializeObject(Data, isoConvert);
response.Write(JsonConvert.SerializeObject(Data, settings));

Upvotes: 2

Alex Alvarez
Alex Alvarez

Reputation: 391

The JsonSerializer instance can be configured to ignore reference loops. Like in the following, this function allows to save a file with the content of the json serialized object:

    public static void SaveJson<T>(this T obj, string FileName)
    {
   
       JsonSerializer serializer = new JsonSerializer();
        serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        using (StreamWriter sw = new StreamWriter(FileName))
        {
            using (JsonWriter writer = new JsonTextWriter(sw))
            {
                writer.Formatting = Formatting.Indented;
                serializer.Serialize(writer, obj);
            }
        }
    }

Upvotes: 2

Karim Tingdis
Karim Tingdis

Reputation: 190

for asp.net core 3.1.3 this worked for me

services.AddControllers().AddNewtonsoftJson(opt=>{
            opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });

Upvotes: 7

Ang&#233;lica Tovar
Ang&#233;lica Tovar

Reputation: 11

Sometimes you have loops becouse your type class have references to other classes and that classes have references to your type class, thus you have to select the parameters that you need exactly in the json string, like this code.

List<ROficina> oficinas = new List<ROficina>();
oficinas = /*list content*/;
var x = JsonConvert.SerializeObject(oficinas.Select(o => new
            {
                o.IdOficina,
                o.Nombre
            }));

Upvotes: 1

krishnan2784
krishnan2784

Reputation: 101

I am using Dot.Net Core 3.1 and did an search for

"Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property "

I am adding this to this question, as it will be an easy reference. You should use the following in the Startup.cs file:

 services.AddControllers()
                .AddNewtonsoftJson(options =>
                {
                    // Use the default property (Pascal) casing
                    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
                    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                });

Upvotes: 10

Samet Sunman
Samet Sunman

Reputation: 359

Add "[JsonIgnore]" to your model class

{
  public Customer()
  {
    Orders = new Collection<Order>();
  }

public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }

[JsonIgnore]
public ICollection<Order> Orders { get; set; }
}

Upvotes: 7

Cyrus
Cyrus

Reputation: 2429

You must set Preserving Object References:

var jsonSerializerSettings = new JsonSerializerSettings
{
    PreserveReferencesHandling = PreserveReferencesHandling.Objects
};

Then call your query var q = (from a in db.Events where a.Active select a).ToList(); like

string jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(q, jsonSerializerSettings);

See: https://www.newtonsoft.com/json/help/html/PreserveObjectReferences.htm

Upvotes: 10

user3824027
user3824027

Reputation: 450

JsonConvert.SerializeObject(ObjectName, new JsonSerializerSettings(){ PreserveReferencesHandling = PreserveReferencesHandling.Objects, Formatting = Formatting.Indented });

Upvotes: 2

andreisrob
andreisrob

Reputation: 1715

If using ASP.NET Core MVC, add this to the ConfigureServices method of your startup.cs file:

services.AddMvc()
    .AddJsonOptions(
        options => options.SerializerSettings.ReferenceLoopHandling =            
        Newtonsoft.Json.ReferenceLoopHandling.Ignore
    );

Upvotes: 46

I just had the same problem with Parent/Child collections and found that post which has solved my case. I Only wanted to show the List of parent collection items and didn't need any of the child data, therefore i used the following and it worked fine:

JsonConvert.SerializeObject(ResultGroups, Formatting.None,
                        new JsonSerializerSettings()
                        { 
                            ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                        });

JSON.NET Error Self referencing loop detected for type

it also referes to the Json.NET codeplex page at:

http://json.codeplex.com/discussions/272371

Documentation: ReferenceLoopHandling setting

Upvotes: 383

ddagsan
ddagsan

Reputation: 1826

This may help you.

public MyContext() : base("name=MyContext") 
{ 
    Database.SetInitializer(new MyContextDataInitializer()); 
    this.Configuration.LazyLoadingEnabled = false; 
    this.Configuration.ProxyCreationEnabled = false; 
} 

http://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

Upvotes: 13

smockle
smockle

Reputation: 2312

The fix is to ignore loop references and not to serialize them. This behaviour is specified in JsonSerializerSettings.

Single JsonConvert with an overload:

JsonConvert.SerializeObject((from a in db.Events where a.Active select a).ToList(), Formatting.Indented,
    new JsonSerializerSettings() {
        ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
    }
);

If you'd like to make this the default behaviour, add a Global Setting with code in Application_Start() in Global.asax.cs:

JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
     Formatting = Newtonsoft.Json.Formatting.Indented,
     ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};

Reference: https://github.com/JamesNK/Newtonsoft.Json/issues/78

Upvotes: 58

Related Questions