Domanda

Come posso serializzare l'oggetto framework di entità in JavaScript Object (JSON)? Ho provato a utilizzare JSON.NET ma ricevo la seguente eccezione quando provo a serializzarlo.

Eccezione: Newtonsoft.Json.JsonSerializationException, Message = " Auto-referencing loop "

Hitesh

È stato utile?

Soluzione

Sembra che tu abbia lo stesso problema generale del serializzatore DataContract originale, per quanto riguarda i riferimenti ciclici. Mentre gli oggetti che si riferiscono a vicenda sono abbastanza comuni con i grafici degli oggetti in memoria, tali riferimenti ciclici comportano inevitabilmente ricorsioni infinite quando serializzati se il serializzatore non lo tiene conto in modo specifico. Esistono pochi standard, se presenti, per gestire i riferimenti ciclici nei formati di serializzazione non binari comuni (XML e JSON sono i due più diffusi.)

Microsoft ha risolto il problema ciclico per il serializzatore DataContract in .NET 3.5 SP1 utilizzando la semantica ref in xml. Per quanto ne so, non esiste una cosa del genere per JSON, il che potrebbe essere il motivo per cui JSON.NET ti impedisce di serializzare il tuo grafico a oggetti.

Vorrei assicurarmi che nel grafico degli oggetti siano presenti solo riferimenti navigabili a senso unico, anziché in entrambi i modi (ovvero solo da genitore a figlio, non da figlio a genitore). Questi genitori / figlio e figlio / genitore sono i tipi più comuni di riferimenti ciclici. Può anche darsi che un bambino di livello inferiore stia infine facendo riferimento alla radice del grafico, causando la creazione di un grafico ciclico indiretto (questi tendono ad essere molto meno comuni dei cicli genitore / figlio, tuttavia.)

Una volta eliminati i riferimenti ciclici nel grafico degli oggetti, dovresti essere in grado di serializzare.

Altri suggerimenti

Ho riscontrato questo problema e l'ho risolto aggiungendo Newtonsoft.Json.JsonIgnoreAttribute alla proprietà che ha causato il ciclo. Ovviamente, quella proprietà non verrà serializzata. Per risolvere questo problema, in genere avrò sia l'ID di riferimento straniero che la classe straniera nelle mie entità. Mi rendo conto che questo non è intuitivo (o super eccezionale OO), ma è il modo raccomandato da Julia Lerman nel suo libro Programming Entity Framework: Code First. Ho scoperto che aiuta a risolvere diversi problemi con Entity Framework.

 public class SomeEntity
 {
      [JsonIgnore]
      public ForeignEntity SomeForeignEntity {get;set;}
      public Guid ForeignEntityId {get;set;}
 }

Aggiornamento: ho dimenticato di dire che dovevo anche disabilitare i proxy su DbContext in questo modo:

dataContext.Configuration.ProxyCreationEnabled = false;

Se stai scrivendo il codice per un servizio (che sembra probabile se stai serializzando), probabilmente questo non è un problema, ma ci sono alcune cose che perdi quando la creazione del proxy è disabilitata. Vedi qui: http://www.sellsbrothers.com/posts/Details/12665 ?? per maggiori dettagli.

Sto usando MS Web Api, quindi disabilito la creazione del proxy quando costruisco il mio controller:

public class MailingApiController : ApiController
{
    public MailingApiController()
    {
        PreventDeepSerialization();
    }

    private static void PreventDeepSerialization()
    {
        var dataContext = Injector.Get<IIntertwyneDbContext>();
        dataContext.Configuration.ProxyCreationEnabled = false;
    }
      ....

Per ovviare a questo, ho convertito prima le mie Entità in codice basato su POCO. Per fare ciò, fai clic con il pulsante destro del mouse nella finestra di edmx e seleziona:

Aggiungi elemento di generazione del codice > Scheda Codice > EF POCO Entity Generator.

Nota che potrebbe non essere necessario installarlo con nuget se non lo vedi.

In fase di esecuzione, tuttavia EF aggiunge classi proxy a quegli oggetti a scopo di tracciamento ma tendono a incasinare il processo di serializzazione. Per evitare ciò, possiamo semplicemente impostare ProxyCreationEnabled su false come segue:

var context = new YourEntities();
context.Configuration.ProxyCreationEnabled = false;

var results = context.YourEntity.Take(100).ToList();

È quindi possibile restituire in modo sicuro i dati serializzati JSON.NET omettendo il loop di riferimento predefinito come segue:

return JsonConvert.SerializeObject(results, Formatting.Indented, 
    new jsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
    });
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top