JSON.NET wykryto błąd Samoodsyłania pętli dla typu

Próbowałem serializować klasę POCO, która została automatycznie wygenerowana z modelu danych podmiotu .edmx i kiedy użyłem

JsonConvert.SerializeObject 

Dostałem następujący błąd:

Wykryto błąd samodzielnej pętli odniesienia dla systemu typu.data./ align = "left" /

Jak rozwiązać ten problem?
Author: Kahbazi, 2011-09-13

17 answers

To było najlepsze rozwiązanie https://code.msdn.microsoft.com/Loop-Reference-handling-in-caaffaf7

Fix 1: ignorowanie odniesienia kołowego globalnie

(wybrałem / wypróbowałem ten, jak wiele innych)

The json.net serializer ma opcję ignorowania odniesień okrągłych. Umieść następujący kod w pliku WebApiConfig.cs:

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

Prosta poprawka sprawi, że serializer zignoruje odniesienie, które spowoduje pętlę. Jednak ma ograniczenia:

Dane tracą zapętloną informację odniesienia Poprawka dotyczy tylko JSON.net Poziom odniesień nie może być kontrolowany, jeśli istnieje głęboki łańcuch odniesienia

Jeśli chcesz użyć tej poprawki w nie-api ASP.NET projekt, możesz dodać powyższą linię do Global.asax.cs, ale najpierw dodaj:

var config = GlobalConfiguration.Configuration;

Jeśli chcesz użyć tego w . Net Core, możesz zmienić Startup.cs jako:

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

Fix 2: zachowanie odniesienia kołowego globalnie

To druga poprawka jest podobna do pierwszej. Po prostu zmień kod na:

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

Kształt danych zostanie zmieniony po zastosowaniu tego ustawienia.

[
   {
      "$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 i $ ref zachowują wszystkie odniesienia i sprawiają, że wykres obiektu jest płaski, ale kod klienta musi znać zmianę kształtu, aby zużyć Dane i odnosi się tylko do JSON.NET serializer również.

Fix 3: Ignoruj i zachowuj atrybuty odniesienia

Ta poprawka jest dekorowaniem atrybutów NA klasie modelu do kontroluj zachowanie serializacji na poziomie modelu lub właściwości. Aby zignorować właściwość:

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

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

JsonIgnore jest dla JSON.NET a IgnoreDataMember jest dla XmlDCSerializer. Aby zachować odniesienie:

 // 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)]jest dla JSON.NET i {[11] } jest dla XmlDCSerializer. Zauważ, że: po zastosowaniu {[12] } na klasie, musisz dodać DataMember do właściwości, które chcesz serializować.

Atrybuty mogą być stosowane zarówno w serializerze json, jak i xml i dają więcej kontroli nad modelem klasy.

 302
Author: Bishoy Hanna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-02 09:49:39

Użyj JsonSerializerSettings

  • ReferenceLoopHandling.Error (domyślnie) spowoduje błąd w przypadku napotkania pętli odniesienia. Dlatego dostajesz wyjątek.
  • ReferenceLoopHandling.Serialize jest przydatne, gdy obiekty są zagnieżdżane, ale nie w nieskończoność.
  • ReferenceLoopHandling.Ignore nie spowoduje serializacji obiektu, jeśli jest on sam w sobie obiektem potomnym.

Przykład:

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

Jeśli musisz serializować obiekt, który jest zagnieżdżony w nieskończoność, możesz użyć PreserveObjectReferences , aby uniknąć StackOverflowException.

Przykład:

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

Wybierz, co ma sens dla obiektu, który serializujesz.

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

 388
Author: DalSoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-13 11:18:39

Poprawką jest ignorowanie odwołań do pętli, a nie serializowanie ich. Zachowanie to jest określone w JsonSerializerSettings.

Single JsonConvert z przeciążeniem:

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

Globalne ustawienie z kodem w {[4] } w globalnym.asax.cs:

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

Numer referencyjny: https://github.com/JamesNK/Newtonsoft.Json/issues/78

 39
Author: smockle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-16 16:34:07

Najprostszym sposobem na to jest zainstalowanie Json.NET z nuget i Dodaj atrybut [JsonIgnore] do wirtualnej właściwości w klasie, na przykład:

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

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

Chociaż w dzisiejszych czasach, tworzę model tylko z właściwościami, które chcę przekazać, więc jest lżejszy, nie zawiera niechcianych kolekcji i nie tracę swoich zmian, gdy odbudowuję wygenerowane pliki...

 30
Author: Sam Jones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-13 09:29:01

W. NET Core 1.0 możesz ustawić to jako globalne ustawienie w swoim starcie.plik 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));
        });
    }
 20
Author: Caleb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-14 18:49:17

Możemy dodać te dwie linie do konstruktora klasy DbContext, aby wyłączyć pętlę odwołującą się do siebie, jak

public TestContext()
        : base("name=TestContext")
{
    this.Configuration.LazyLoadingEnabled = false;
    this.Configuration.ProxyCreationEnabled = false;
}
 6
Author: Sanjay Nishad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-25 14:49:13

Możesz również zastosować atrybut do właściwości. Atrybut [JsonProperty( ReferenceLoopHandling = ... )] dobrze do tego pasuje.

Na przykład:

/// <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...    
}

Hope that helps, Jaans

 4
Author: Jaans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-10 13:11:11

Aby zignorować odwołania do pętli i nie serializować ich globalnie w MVC 6, użyj poniższego przy starcie.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);
        });
    }
 3
Author: GerardBeckerleg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-16 13:53:22

Użyj tego w WebApiConfig.cs klasie:

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
 2
Author: Anand Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-02 08:15:19

Dla mnie musiałem pójść inną drogą. Zamiast próbować naprawić JSON.Net serializer musiałem iść po leniwym ładowaniu na moim datacontext.

Właśnie dodałem to do repozytorium Bazy:

context.Configuration.ProxyCreationEnabled = false;

Obiekt "context" jest parametrem konstruktora, którego używam w repozytorium bazowym, ponieważ używam iniekcji zależności. Możesz zmienić właściwość ProxyCreationEnabled w dowolnym miejscu, w którym utworzysz instancję datacontext zamiast tego.

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

 2
Author: Xipooo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-18 20:21:24

Aby serializować usin NEWTONSOFTJSON gdy masz problem z pętlą, w moim przypadku nie musiałem modyfikować global.asax lub apiconfig. Po prostu używam JsonSerializesSettings ignorując obsługę pętli.

JsonSerializerSettings jss = new JsonSerializerSettings();
jss.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
var lst = db.shCards.Where(m => m.CardID == id).ToList();
string json = JsonConvert.SerializeObject(lst, jss);
 2
Author: Carlos Barini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-22 20:07:49

Miałem ten wyjątek i moje rozwiązanie pracy jest łatwe i proste,

Ignoruj właściwość, o której mowa, dodając do niej atrybut JsonIgnore:

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

Reset właściwości po deserializacji:

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

Korzystanie Z Newtonsoft.Json;

 2
Author: Mayer Sariggs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-09 18:06:27

Jeśli używasz. NET Core 2.0, zaktualizuj sekcję ConfigureServices podczas uruchamiania.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
    );

...
}
 1
Author: Dave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-09 15:31:46

Ludzie już mówili o [JsonIgnore] do dodania do wirtualnej właściwości w klasie, na przykład:

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

Podzielę się również inną opcją, [JsonProperty (NullValueHandling = NullValueHandling.Ignoruj)], która pomija właściwość z serializacji tylko wtedy, gdy jest null.

[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public virtual Project Project { get; set; }
 1
Author: Ali Raza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-12 19:55:55

Po prostu umieść Configuration.ProxyCreationEnabled = false; wewnątrz pliku kontekstowego; to rozwiąże problem.

public demEntities()
    : base("name=demEntities")
{
    Configuration.ProxyCreationEnabled = false;
}
 0
Author: Fravius Kalisa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-05 15:30:09

Za to, że nie zapętlenie tego mi się udało-
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,

Rozwiązałem to wszystko tutaj-Entity Framework children serialization with. Net Core 2 WebAPI https://gist.github.com/Kaidanov/f9ad0d79238494432f32b8407942c606

Będę wdzięczna za wszelkie uwagi. może ktoś go kiedyś użyje.
 -1
Author: Tzvi Gregory Kaidanov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-18 10:32:30

Podobało mi się rozwiązanie, które robi to z Application_Start() jak w odpowiedzi Tutaj

Najwyraźniej nie mogłem uzyskać dostępu do obiektów json w JavaScript, używając konfiguracji w mojej funkcji, jak w odpowiedzi DalSoft, ponieważ zwrócony obiekt miał "\N \ r " na całym (key, val) obiektu.

W każdym razie cokolwiek działa jest świetne (ponieważ różne podejścia działają w różnych scenariuszach na podstawie komentarzy i zadawanych pytań) choć standardowy sposób to zrobić byłoby lepsze z dobra dokumentacja wspierająca to podejście.

 -2
Author: rey_coder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:24