Errore JSON.NET Ciclo di riferimento automatico rilevato per il tipo


495

Ho provato a serializzare la classe POCO che è stata generata automaticamente da Entity Data Model .edmx e quando l'ho usata

JsonConvert.SerializeObject 

Ho ricevuto il seguente errore:

Errore Si verifica un ciclo di autoreferenziazione rilevato per il tipo System.data.entity.

Come posso risolvere questo problema?



quando si utilizza LINQ e MVC: stackoverflow.com/a/38241856
Addin

quando si utilizza .NET Core 2: stackoverflow.com/a/48709134/4496145
Dave Skender

2
Questo errore mi è successo quando volevo serializzare il risultato di una asyncchiamata al metodo (a Task) e ho dimenticato di aggiungere il prefisso awaitall'istruzione.
Uwe Keim,

Risposte:


485

Quella era la soluzione migliore https://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

Correzione 1: ignorare il riferimento circolare a livello globale

(Ho scelto / provato questo, come molti altri)

Il serializzatore json.net ha un'opzione per ignorare i riferimenti circolari. Inserisci il seguente codice nel WebApiConfig.csfile:

 config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling 
= Newtonsoft.Json.ReferenceLoopHandling.Ignore; 

La semplice correzione consentirà al serializzatore di ignorare il riferimento che causerà un ciclo. Tuttavia, ha dei limiti:

  • I dati perdono le informazioni di riferimento del loop
  • La correzione si applica solo a JSON.net
  • Il livello di riferimenti non può essere controllato se esiste una catena di riferimento profonda

Se si desidera utilizzare questa correzione in un progetto ASP.NET non api, è possibile aggiungere la riga precedente a Global.asax.cs, ma prima aggiungere:

var config = GlobalConfiguration.Configuration;

Se vuoi usarlo nel progetto .Net Core , puoi cambiare Startup.cscome:

  var mvc = services.AddMvc(options =>
        {
           ...
        })
        .AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

Correzione 2: conservazione del riferimento circolare a livello globale

Questa seconda correzione è simile alla prima. Basta cambiare il codice in:

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling 
     = Newtonsoft.Json.ReferenceLoopHandling.Serialize;     
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling 
     = Newtonsoft.Json.PreserveReferencesHandling.Objects;

La forma dei dati verrà modificata dopo aver applicato questa impostazione.

[
   {
      "$id":"1",
      "Category":{
         "$id":"2",
         "Products":[
            {
               "$id":"3",
               "Category":{
                  "$ref":"2"
               },
               "Id":2,
               "Name":"Yogurt"
            },
            {
               "$ref":"1"
            }
         ],
         "Id":1,
         "Name":"Diary"
      },
      "Id":1,
      "Name":"Whole Milk"
   },
   {
      "$ref":"3"
   }
]

$ Id e $ ref mantengono tutti i riferimenti e rendono piatto il livello del grafico dell'oggetto, ma il codice client deve conoscere la modifica della forma per consumare i dati e si applica anche al serializzatore JSON.NET.

Correzione 3: ignora e conserva gli attributi di riferimento

Questa correzione è decorare gli attributi sulla classe del modello per controllare il comportamento della serializzazione a livello di modello o proprietà. Per ignorare la proprietà:

 public class Category 
    { 
        public int Id { get; set; } 
        public string Name { get; set; } 

        [JsonIgnore] 
        [IgnoreDataMember] 
        public virtual ICollection<Product> Products { get; set; } 
    } 

JsonIgnore è per JSON.NET e IgnoreDataMember è per XmlDCSerializer. Per conservare il riferimento:

 // Fix 3 
        [JsonObject(IsReference = true)] 
        public class Category 
        { 
            public int Id { get; set; } 
            public string Name { get; set; } 

           // Fix 3 
           //[JsonIgnore] 
           //[IgnoreDataMember] 
           public virtual ICollection<Product> Products { get; set; } 
       } 

       [DataContract(IsReference = true)] 
       public class Product 
       { 
           [Key] 
           public int Id { get; set; } 

           [DataMember] 
           public string Name { get; set; } 

           [DataMember] 
           public virtual Category Category { get; set; } 
       }

JsonObject(IsReference = true)]è per JSON.NET ed [DataContract(IsReference = true)]è per XmlDCSerializer. Nota che: dopo l'applicazione DataContractsulla classe, devi aggiungere DataMemberalle proprietà che vuoi serializzare.

Gli attributi possono essere applicati sia sul serializzatore json che xml e offrono più controlli sulla classe del modello.


7
Fix 3 ha funzionato per me. Basta semplicemente rimuovere gli attributi DataContract e DataMember e inserire JsonObject (IsReference = true) sui DTO. E funziona Grazie.
maestro

1
prova questo GlobalConfiguration.Configuration
Bishoy Hanna il

1
La correzione 3 ha il vantaggio di funzionare sul codice client in cui non esiste GlobalConfiguration
silente

1
@BishoyHanna, puoi modificare la tua risposta per consentirne l'utilizzo dalle normali applicazioni ASP.NET? Puoi usare la mia modifica suggerita: stackoverflow.com/review/suggested-edits/17797683
NH.

2
Usando [JsonIgnore]sopra l'attributo ha funzionato per me.
Nathan Beck,

467

Utilizzare JsonSerializerSettings

  • ReferenceLoopHandling.Error(impostazione predefinita) genererà un errore se viene rilevato un loop di riferimento. Questo è il motivo per cui ottieni un'eccezione.
  • ReferenceLoopHandling.Serialize è utile se gli oggetti sono nidificati ma non indefinitamente.
  • ReferenceLoopHandling.Ignore non serializzerà un oggetto se è un oggetto figlio di se stesso.

Esempio:

JsonConvert.SerializeObject(YourPOCOHere, Formatting.Indented, 
new JsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Serialize
});

Se è necessario serializzare un oggetto nidificato indefinitamente, è possibile utilizzare PreserveObjectReferences per evitare StackOverflowException.

Esempio:

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

Scegli ciò che ha senso per l'oggetto che stai serializzando.

Riferimento http://james.newtonking.com/json/help/


66
Ho riscontrato l'errore durante la serializzazione di un datatable. Ho usato ReferenceLoopHandling = ReferenceLoopHandling.Ignoreper farlo funzionare

8
Se ci sono loop di riferimento nei dati, l'uso ReferenceLoopHandling.Serializefarà sì che il serializzatore entri in un ciclo ricorsivo infinito e trabocchi lo stack.
Brian Rogers,

1
Corretta. Poiché la domanda riguarda un modello EF, anche una preoccupazione valida. Modificato per fornire tutte le opzioni disponibili.
DalSoft,

1
Ho riscontrato questo stesso errore durante il tentativo di serializzare un oggetto ... tuttavia, l'oggetto non ha riferimenti diversi da un tipo enum ..
Marin,

1
per me EF è la causa principale di questo problema perché le entità autoreferenziali si trovano ovunque.
Teoman Shipahi,

58

La correzione è ignorare i riferimenti di loop e non serializzarli. Questo comportamento è specificato in JsonSerializerSettings.

SingoloJsonConvert con un sovraccarico:

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

Impostazioni globali con codice Application_Start()in Global.asax.cs:

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

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


Perché imposti il ​​formato su rientro quando esegui l'impostazione globale?
Murphybro2,

Assolutamente ciò di cui avevamo bisogno per risolvere questo problema (scoperto durante una distribuzione)! Amico .... grazie per averci risparmiato tempo !!
Ryan Eastabrook,

Ho risolto il mio issus aggiungendo "JsonConvert.DefaultSettings" = () => new JsonSerializerSettings {....} nella classe "Startup.cs"
Beldi Anouar

45

Il modo più semplice per farlo è installare Json.NET dal nuget e aggiungere l' [JsonIgnore]attributo alla proprietà virtuale nella classe, ad esempio:

    public string Name { get; set; }
    public string Description { get; set; }
    public Nullable<int> Project_ID { get; set; }

    [JsonIgnore]
    public virtual Project Project { get; set; }

Anche se in questi giorni, creo un modello con solo le proprietà che desidero passare, quindi è più leggero, non include raccolte indesiderate e non perdo le modifiche quando ricostruisco i file generati ...


3
Migliore risposta usando Newton JSON
Aizen il

21

In .NET Core 1.0, puoi impostarlo come impostazione globale nel tuo file Startup.cs:

using System.Buffers;
using Microsoft.AspNetCore.Mvc.Formatters;
using Newtonsoft.Json;

// beginning of Startup class

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(options =>
        {
            options.OutputFormatters.Clear();
            options.OutputFormatters.Add(new JsonOutputFormatter(new JsonSerializerSettings(){
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            }, ArrayPool<char>.Shared));
        });
    }

Ma in questo caso, se voglio essere consapevole che questa proprietà è ignorata, non otterrò alcuna eccezione.
Mayer Spitzer,

10

Se si utilizza .NET Core 2.x, aggiornare la sezione ConfigureServices in Startup.cs

https://docs.microsoft.com/en-us/ef/core/querying/related-data#related-data-and-serialization

    public void ConfigureServices(IServiceCollection services)
    {
    ...

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

    ...
    }

Se si utilizza .NET Core 3.x senza MVC, sarebbe:

services.AddControllers()
  .AddNewtonsoftJson(options =>
      options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
   );

Questa gestione del loop di riferimento è quasi obbligatoria se si utilizza Entity Framework e il modello di progettazione basato sul database.


2
cosa succede se non uso services.AddMvc()?
prisar,

2
è una cattiva pratica?
Renan Coelho,

A prima vista potresti pensare che questa sia una cattiva pratica in quanto potrebbe scavalcare il "disegno intenzionale" per evitare il vecchio problema del "ciclo infinito". Tuttavia, se pensi ai tuoi casi d'uso per le classi, potresti aver bisogno che si riferiscano l'un l'altro. Ad esempio, potresti voler accedere a Alberi> Frutta e anche Frutta> Alberi.
Dave Skender,

Inoltre, se si utilizza un modello di progettazione basato sul database con qualcosa come Entity Framework, a seconda di come si impostano le chiavi esterne nel database, verranno automaticamente creati questi riferimenti ciclici, quindi è necessario utilizzare questa impostazione se si retroingegnerizza le tue lezioni.
Dave Skender,

9

Per serializzarci su NEWTONSOFTJSON in caso di problemi di loop, nel mio caso non ho avuto bisogno di modificare global.asax o apiconfig. Uso solo JsonSerializesSettings ignorando la gestione dei loop.

JsonSerializerSettings jss = new JsonSerializerSettings();
jss.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
var lst = db.shCards.Where(m => m.CardID == id).ToList();
string json = JsonConvert.SerializeObject(lst, jss);

1
Se qualcun altro venisse qui per una sola fodera per entrare nella finestra dell'orologio, quindi è possibile effettuare ricerche di testo:Newtonsoft.Json.JsonConvert.SerializeObject(objToSerialize, new Newtonsoft.Json.JsonSerializerSettings() {ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore});
Graham,

8

Possiamo aggiungere queste due righe nel costruttore della classe DbContext per disabilitare il ciclo di auto-riferimento, come

public TestContext()
        : base("name=TestContext")
{
    this.Configuration.LazyLoadingEnabled = false;
    this.Configuration.ProxyCreationEnabled = false;
}

Questo è uno dei più semplici e funziona come un fascino . Votato, grazie mille ...
Murat Yıldız il

Come ho scritto nell'altra domanda: non mi piace questo tipo di risposte perché stai disattivando una funzione di EF6 che è abilitata di default e questo pezzo di codice potrebbe spezzare altre parti del programma. Dovresti spiegare cosa fa questo e che tipo di ripercussioni ha.
El Mac,

@ElMac hai ragione, ma se non abbiamo bisogno di quella funzione, perché non possiamo usare questa soluzione?
Sanjay Nishad,

@SanjayNishad Non mi dispiace se non hai bisogno della funzione. Si tratta solo degli utenti che non sanno cosa stanno disabilitando.
El Mac,

6

È possibile applicare un attributo anche alla proprietà. L' [JsonProperty( ReferenceLoopHandling = ... )]attributo è adatto a questo.

Per esempio:

/// <summary>
/// Represents the exception information of an event
/// </summary>
public class ExceptionInfo
{
    // ...code omitted for brevity...

    /// <summary>
    /// An inner (nested) error.
    /// </summary>
    [JsonProperty( ReferenceLoopHandling = ReferenceLoopHandling.Ignore, IsReference = true )]
    public ExceptionInfo Inner { get; set; }

    // ...code omitted for brevity...    
}

Spero che ti aiuti, Jaans


4

Per ignorare i riferimenti di loop e non serializzarli globalmente in MVC 6, utilizzare startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().Configure<MvcOptions>(options =>
        {
            options.OutputFormatters.RemoveTypesOf<JsonOutputFormatter>();
            var jsonOutputFormatter = new JsonOutputFormatter();
            jsonOutputFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            options.OutputFormatters.Insert(0, jsonOutputFormatter);
        });
    }

2

Usa questo in WebApiConfig.csclasse:

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);

2

Per me ho dovuto percorrere una strada diversa. Invece di provare a riparare il serializzatore JSON.Net ho dovuto seguire il Lazy Loading sul mio datacontext.

Ho appena aggiunto questo al mio repository di base:

context.Configuration.ProxyCreationEnabled = false;

L'oggetto "contesto" è un parametro costruttore che uso nel mio repository di base perché utilizzo l'iniezione di dipendenza. In alternativa, è possibile modificare la proprietà ProxyCreationEnabled in qualsiasi punto di un'istanza del datacontext.

http://techie-tid-bits.blogspot.com/2015/09/jsonnet-serializer-and-error-self.html


2

Ho avuto questa eccezione e la mia soluzione di lavoro è facile e semplice,

Ignora la proprietà Referenced aggiungendo l'attributo JsonIgnore ad essa:

[JsonIgnore]
public MyClass currentClass { get; set; }

Reimposta la proprietà quando la deserializzi:

Source = JsonConvert.DeserializeObject<MyObject>(JsonTxt);
foreach (var item in Source)
        {
            Source.MyClass = item;
        }

utilizzando Newtonsoft.Json;


Questa è la magia di cui ho bisogno. Risolverlo[JsonIgnore]
saviour123

2

Squadra:

Funziona con ASP.NET Core; La sfida di cui sopra è come 'impostare l'impostazione da ignorare'. A seconda di come si configura l'applicazione, può essere piuttosto impegnativo. Ecco cosa ha funzionato per me.

Questo può essere inserito nella sezione ConfigureServices (servizi IServiceCollection) vuota del tuo pubblico.

services.AddMvc().AddJsonOptions(opt => 
        { 
      opt.SerializerSettings.ReferenceLoopHandling =
      Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });

2

Le persone hanno già parlato dell'aggiunta di [JsonIgnore] alla proprietà virtuale nella classe, ad esempio:

[JsonIgnore]
public virtual Project Project { get; set; }

Condividerò anche un'altra opzione, [JsonProperty (NullValueHandling = NullValueHandling.Ignore)] che omette la proprietà dalla serializzazione solo se è nulla:

[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public virtual Project Project { get; set; }


0

Posizionalo semplicemente Configuration.ProxyCreationEnabled = false;all'interno del file di contesto; questo risolverà il problema.

public demEntities()
    : base("name=demEntities")
{
    Configuration.ProxyCreationEnabled = false;
}

0

Il mio problema è stato risolto con la configurazione personalizzata JsonSerializerSettings:

services.AddMvc(
  // ...
               ).AddJsonOptions(opt =>
                 {
                opt.SerializerSettings.ReferenceLoopHandling =
                    Newtonsoft.Json.ReferenceLoopHandling.Serialize;
                opt.SerializerSettings.PreserveReferencesHandling =
                    Newtonsoft.Json.PreserveReferencesHandling.Objects;
                 });

0

Assicurati anche di utilizzare wait e async nel tuo metodo. È possibile ottenere questo errore se l'oggetto non è serializzato correttamente.


0

Stavo affrontando lo stesso problema e ho provato a usare JsonSetting per ignorare l'errore di autoreferenziazione che ha funzionato fino a quando non ho ottenuto una classe che si auto-referenzia molto profondamente e il mio processo dot-net si blocca sul valore di scrittura di Json.

Il mio problema

    public partial class Company : BaseModel
{
    public Company()
    {
        CompanyUsers = new HashSet<CompanyUser>();
    }

    public string Name { get; set; }

    public virtual ICollection<CompanyUser> CompanyUsers { get; set; }
}

public partial class CompanyUser
{
    public int Id { get; set; }
    public int CompanyId { get; set; }
    public int UserId { get; set; }

    public virtual Company Company { get; set; }

    public virtual User User { get; set; }
}

public partial class User : BaseModel
{
    public User()
    {
        CompanyUsers = new HashSet<CompanyUser>();
    }

    public string DisplayName { get; set; }
    public virtual ICollection<CompanyUser> CompanyUsers { get; set; }

}

Puoi vedere il problema nella classe Utente che fa riferimento alla classe CompanyUser che è un auto-riferimento.

Ora sto chiamando il metodo GetAll che include tutte le proprietà relazionali.

cs.GetAll("CompanyUsers", "CompanyUsers.User");

In questa fase il mio processo DotNetCore si blocca sull'esecuzione di JsonResult, scrivendo valore ... e non arriva mai. Nel mio Startup.cs, ho già impostato JsonOption. Per qualche motivo EFCore include la proprietà nidificata che non sto chiedendo a Ef di dare.

    options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

il comportamento previsto dovrebbe essere questo

Ehi EfCore, per favore, puoi includere anche i dati di "CompanyUsers" nella mia classe aziendale in modo che io possa accedere facilmente ai dati.

poi

Ehi EfCore puoi anche includere i dati "CompanyUsers.User" in modo da poter accedere facilmente ai dati come questo Company.CompanyUsers.First (). User.DisplayName

a questo punto dovrei ottenere questo "Company.CompanyUsers.First (). User.DisplayName" e non dovrei darmi Company.CompanyUsers.First (). User.CompanyUsers che causano il problema di autoreferenziazione; Tecnicamente non dovrebbe darmi User.CompanyUsers come CompanyUsers è una proprietà di navigazione. Ma EfCore si emoziona molto e mi dà User.CompanyUsers .

Quindi, ho deciso di scrivere un metodo di estensione per escludere la proprietà dall'oggetto (in realtà non si esclude, è solo impostare la proprietà su null). Non solo funzionerà anche con le proprietà dell'array. sotto è il codice che vado anche ad esportare il pacchetto nuget per altri utenti (non sono sicuro che ciò aiuti anche qualcuno). Il motivo è semplice perché sono troppo pigro per scrivere .Seleziona (n => nuovo {n.p1, n.p2}); Non voglio solo scrivere un'istruzione select per escludere solo 1 proprietà!

Questo non è il codice migliore (lo aggiornerò a un certo punto) come ho scritto in fretta e anche se questo potrebbe aiutare qualcuno che vuole escludere (impostare null) anche nell'oggetto con array.

    public static class PropertyExtensions
{
    public static void Exclude<T>(this T obj, Expression<Func<T, object>> expression)
    {
        var visitor = new PropertyVisitor<T>();
        visitor.Visit(expression.Body);
        visitor.Path.Reverse();
        List<MemberInfo> paths = visitor.Path;
        Action<List<MemberInfo>, object> act = null;

        int recursiveLevel = 0;
        act = (List<MemberInfo> vPath, object vObj) =>
        {

            // set last propert to null thats what we want to avoid the self-referencing error.
            if (recursiveLevel == vPath.Count - 1)
            {
                if (vObj == null) throw new ArgumentNullException("Object cannot be null");

                vObj.GetType().GetMethod($"set_{vPath.ElementAt(recursiveLevel).Name}").Invoke(vObj, new object[] { null });
                return;
            }

            var pi = vObj.GetType().GetProperty(vPath.ElementAt(recursiveLevel).Name);
            if (pi == null) return;
            var pv = pi.GetValue(vObj, null);
            if (pi.PropertyType.IsArray || pi.PropertyType.Name.Contains("HashSet`1") || pi.PropertyType.Name.Contains("ICollection`1"))
            {
                var ele = (IEnumerator)pv.GetType().GetMethod("GetEnumerator").Invoke(pv, null);

                while (ele.MoveNext())
                {
                    recursiveLevel++;
                    var arrItem = ele.Current;

                    act(vPath, arrItem);

                    recursiveLevel--;
                }

                if (recursiveLevel != 0) recursiveLevel--;
                return;
            }
            else
            {
                recursiveLevel++;
                act(vPath, pv);
            }

            if (recursiveLevel != 0) recursiveLevel--;

        };

        // check if the root level propert is array
        if (obj.GetType().IsArray)
        {
            var ele = (IEnumerator)obj.GetType().GetMethod("GetEnumerator").Invoke(obj, null);
            while (ele.MoveNext())
            {
                recursiveLevel = 0;
                var arrItem = ele.Current;

                act(paths, arrItem);
            }
        }
        else
        {
            recursiveLevel = 0;
            act(paths, obj);
        }

    }

    public static T Explode<T>(this T[] obj)
    {
        return obj.FirstOrDefault();
    }

    public static T Explode<T>(this ICollection<T> obj)
    {
        return obj.FirstOrDefault();
    }
}

sopra la classe di estensione ti darà la possibilità di impostare la proprietà su null per evitare persino il ciclo di autoreferenziazione.

Generatore di espressioni

    internal class PropertyVisitor<T> : ExpressionVisitor
{
    public readonly List<MemberInfo> Path = new List<MemberInfo>();

    public Expression Modify(Expression expression)
    {
        return Visit(expression);
    }


    protected override Expression VisitMember(MemberExpression node)
    {
        if (!(node.Member is PropertyInfo))
        {
            throw new ArgumentException("The path can only contain properties", nameof(node));
        }

        Path.Add(node.Member);
        return  base.VisitMember(node);
    }
}

usi:

Classi di modello

    public class Person
{
    public string Name { get; set; }
    public Address AddressDetail { get; set; }
}

public class Address
{
    public string Street { get; set; }
    public Country CountryDetail { get; set; }
    public Country[] CountryDetail2 { get; set; }
}

public class Country
{
    public string CountryName { get; set; }
    public Person[] CountryDetail { get; set; }
}

Dati fittizi

           var p = new Person
        {
            Name = "Adeel Rizvi",
            AddressDetail = new Address
            {
                Street = "Sydney",
                CountryDetail = new Country
                {
                    CountryName = "AU"
                }
            }
        };

        var p1 = new Person
        {
            Name = "Adeel Rizvi",
            AddressDetail = new Address
            {
                Street = "Sydney",
                CountryDetail2 = new Country[]
                {
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A1" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A2" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A3" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A4" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A5" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A6" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A7" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A8" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A9" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A1" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A2" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A3" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A4" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A5" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A6" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A7" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A8" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },
                    new Country{ CountryName = "AU", CountryDetail = new Person[]{ new Person { Name = "A9" }, new Person { Name = "A1" }, new Person { Name = "A1" } } },

                }
            }
        };

casi:

Caso 1: escludere solo la proprietà senza alcun array

p.Exclude(n => n.AddressDetail.CountryDetail.CountryName);

Caso 2: Escludere la proprietà con 1 array

p1.Exclude(n => n.AddressDetail.CountryDetail2.Explode().CountryName);

Caso 3: Escludere la proprietà con 2 array nidificati

p1.Exclude(n => n.AddressDetail.CountryDetail2.Explode().CountryDetail.Explode().Name);

Caso 4: EF GetAll Query con include

var query = cs.GetAll("CompanyUsers", "CompanyUsers.User").ToArray();
query.Exclude(n => n.Explode().CompanyUsers.Explode().User.CompanyUsers);
return query;

Si è notato che il metodo Explode () è anche un metodo di estensione solo per il nostro generatore di espressioni per ottenere la proprietà dalla proprietà array. Ogni volta che esiste una proprietà array, utilizzare .Explode (). YourPropertyToExclude o .Explode (). Property1.MyArrayProperty.Explode (). MyStupidProperty . Il codice sopra mi aiuta a evitare l'auto-riferimento tanto profondo quanto profondo voglio. Ora posso usare GetAll ed escludere la proprietà che non desidero!

Grazie per aver letto questo grande post!



-1

Codice C #:

            var jsonSerializerSettings = new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                PreserveReferencesHandling = PreserveReferencesHandling.Objects,
            };

            var jsonString = JsonConvert.SerializeObject(object2Serialize, jsonSerializerSettings);

            var filePath = @"E:\json.json";

            File.WriteAllText(filePath, jsonString);

Questa è essenzialmente la stessa guida offerta nella risposta molto apprezzata di @ DalSoft di otto anni fa, ma con molte meno spiegazioni.
Jeremy Caney,

Spero che risolva il problema, ma ti preghiamo di aggiungere una spiegazione del tuo codice con esso in modo che l'utente possa capire perfettamente ciò che desidera davvero.
Jaimil Patel,

-2

Mi è piaciuta la soluzione che lo fa Application_Start()come nella risposta qui

Apparentemente non sono riuscito ad accedere agli oggetti json in JavaScript usando la configurazione all'interno della mia funzione come nella risposta di DalSoft poiché l'oggetto restituito aveva "\ n \ r" su tutta la (chiave, val) dell'oggetto.

Ad ogni modo, qualunque cosa funzioni è eccezionale (perché approcci diversi funzionano in scenari diversi in base ai commenti e alle domande poste), sebbene un modo standard di farlo sarebbe preferibile con una buona documentazione a supporto dell'approccio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.