JSON.Net 자체 참조 루프 감지


111

4 개의 테이블 내에 내 웹 사이트에 대한 mssql 데이터베이스가 있습니다.

이것을 사용할 때 :

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());
    }
}

이 코드는 다음 오류를 발생시킵니다.

Newtonsoft.Json.JsonSerializationException : 'DAL.CyberUser'유형의 'CyberUser'속성에 대해 자체 참조 루프가 감지되었습니다. 경로 '[0] .EventRegistrations [0] .CyberUser.UserLogs [0]'.



내 대답이 맞다면 표시해 주시겠습니까? @Kovu
무하마드 오마르 ElShourbagy

답변:


212

부모 / 자식 컬렉션에 대해 동일한 문제가 발생했으며 해당 게시물이 내 사례를 해결했습니다. 부모 컬렉션 항목 목록 만 표시하고 싶었고 자식 데이터가 필요하지 않았으므로 다음을 사용했으며 제대로 작동했습니다.

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

JSON.NET 오류 자체 참조 루프가 유형에 대해 감지되었습니다.

또한 다음 위치의 Json.NET codeplex 페이지를 참조합니다.

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

문서 : ReferenceLoopHandling 설정


2
당신은 또한 사용할 수 있습니다 경우에 따라서는 PreserveReferencesHandling = PreserveReferencesHandling.Objects;같은 여기에서 설명 : 해결-자체 참조 - 루프 문제-때 - 사용 - newtonsoft-JSON을
디미트리 Troncquo

WebAPI 중 하나로, OData V4, 나는 일부 데이터 유형이 ReferenceLoopHandling.Ignore 및 PreserveReferencesHandling.Objects 모두 필요한 것을 발견
크리스 쉘러

1
노래 Allelluiah의 감사 (1)에 의해 너무 많은까지만-투표가 충분하지 않습니다
JP Chapleau

42

수정 사항은 루프 참조를 무시하고 직렬화하지 않는 것입니다. 이 동작은 JsonSerializerSettings.

JsonConvert과부하가있는 싱글 :

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

이것을 기본 동작으로 만들려면 Global.asax.cs에 코드가 있는 전역 설정 을 추가합니다 Application_Start().

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

참조 : https://github.com/JamesNK/Newtonsoft.Json/issues/78


3
이것으로 직렬화는 저에게 매우 오랜 시간이 걸립니다
daniel

이것은 순환 루프가있는 객체가 NHibernate 모델 POCO 일 때 작동하지 않는 것 같습니다 (이 경우 직렬화는 많은 쓰레기를 검색하거나 때로는 시간 초과).
Fernando Gonzalez Sanchez

"IsSecuritySafeCritical": false, "IsSecurityTransparent": false, "MethodHandle": { "Value": { "value": 140716810003120}}, "Attributes": 150, "CallingConvention": 1, "ReturnType": "System.Void , System.Private.CoreLib, 버전 = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e ","ReturnTypeCustomAttributes ": {"ParameterType ":"System.Void, System.Private.CoreLib, 버전 = 4.0.0.0, Culture = neutral, PublicKeyToken = 7cec85d7bea7798e ","Name ": null,"HasDefaultValue ": true,"DefaultValue ": null,"RawDefaultValue ": null,"MetadataToken ": 134217728,"Attributes ": 0,"Position ":-1, "IsIn": false, "IsLcid": false ,. ... 등

37

ASP.NET Core MVC를 사용하는 경우 다음을 startup.cs 파일의 ConfigureServices 메서드에 추가합니다.

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

2
이 솔루션은 WebAPI EntityFramework Core 2.0에서도 작동 함을 확인했습니다.
cesar-moya

13

이것은 당신을 도울 수 있습니다.

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


4
이것은 비동기 메서드를 사용하는 경우에 접근하는 가장 좋은 방법입니다. 정말 고통 스러울 수 있지만, 그렇지 않으면 (이 문제를 포함하여) 가질 수있는 많은 문제를 해결하고 사용할 항목 만 쿼리하므로 훨씬 더 성능이 향상 될 수 있습니다.
조쉬 McKearin

xyz.edmx에서 기본적으로 숨겨지는 xyz.Context.vb 파일을 엽니 다. 여기에는 codePublic Sub New () Mybase.New ( "name = EntityConName") End Sub가 code있습니다. 이제 End Sub 추가하기 전에 codeMe.Configuration.LazyLoadingEnabled = False Me.Configuration.ProxyCreationEnabled = False code 그러면 webapi 의 json 출력에서 ​​'Self referencing loop'오류가 제거됩니다.
Venkat

나는 이것이 나를 위해 작동하지 않는다는 것을 알았습니다. AsNoTracking ()을 사용했고 수정했습니다. 어쩌면 다른 사람을 도울 수 있습니다
scottsanpedro

@scottsanpedro 우리가 당신의 코드를 볼 수 있다면 더 좋았습니다.
따 당산

6

객체 참조 보존을 설정해야합니다.

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

그런 다음 쿼리를 다음 var q = (from a in db.Events where a.Active select a).ToList();과 같이 호출하십시오.

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

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


4

모델 클래스에 "[JsonIgnore]"추가

{
  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; }
}

3

Dot.Net Core 3.1을 사용하고 있으며

"Newtonsoft.Json.JsonSerializationException : 속성에 대해 자체 참조 루프가 감지되었습니다."

쉬운 참조가 될 것이므로이 질문에 이것을 추가하고 있습니다. Startup.cs 파일에서 다음을 사용해야합니다.

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

2

asp.net core 3.1.3의 경우 이것은 나를 위해 일했습니다.

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

1

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


6
이 코드가 질문에 답할 수는 있지만이 코드가 질문에 대한 답변 이유 및 / 또는 방법에 대한 추가 컨텍스트를 제공하면 장기적인 가치가 향상됩니다.
Alex Riabov 2018

1

유형 클래스에 다른 클래스에 대한 참조가 있고 해당 클래스에 유형 클래스에 대한 참조가 있기 때문에 루프가있는 경우가 있으므로이 코드와 같이 json 문자열에서 정확히 필요한 매개 변수를 선택해야합니다.

List<ROficina> oficinas = new List<ROficina>();
oficinas = /*list content*/;
var x = JsonConvert.SerializeObject(oficinas.Select(o => new
            {
                o.IdOficina,
                o.Nombre
            }));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.