簡體   English   中英

在沒有位置的情況下檢測到自引用循環

[英]Self referencing loop detected where there is none

我有一個由TransformationPlanModel的數據模型,該模型又包含IEnumerable<TransformationModel> TransformationPlanModel是根數據傳輸對象。 TransformationModel是其他轉換模型的抽象基類。

摘錄了TransformationPlanModel代碼:

public class TransformationPlanModel
{
    // snip
    public IEnumerable<TransformationModel> Transformations { get; set; }
}

剪下的TransformationModel代碼:

public abstract class TransformationModel
{
    //snip
    public string Key { get; set; }
}

具體的轉換模型之一是RemoveRowsTransformationModel

public class RemoveRowsTransformationModel : TransformationModel
{
    public const string KeyConst = "removeRows";

    public int TopRowsCount { get; set; }
    public int BottomRowsCount { get; set; }

    public RemoveRowsTransformationModel()
    {
        Key = KeyConst;
    }

    //snip
}

我已經編寫了一個自定義JsonConverter ,它可以轉換TransformationModel繼承樹。 JsonWrite方法的實現是:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    JObject.FromObject(value, serializer).WriteTo(writer);
}

自定義轉換器在ASP.NET Core API應用程序中使用,並添加到Startup.ConfigureServices方法中的服務中,如下所示:

services.AddMvc().AddJsonOptions(options =>
{
    options.SerializerSettings.Converters.Add(new TransformationConverter());
});

當從API端點作為響應返回TransformationPlanModel並進行序列化時,將引發Newtonsoft.Json.JsonSerializationException ,其中包含以下消息:“檢測到類型為'(...)。RemoveRowsTransformationModel'的自引用循環”。 是什么導致此異常? 我看不到自我引用循環在哪里。 我不知道這是否重要,但是我正在使用.NET Core 2.0 Preview 1。

有趣的是,當過載JObject.FromObject而不串行參數在使用WriteJson方法,它工作正常:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    JObject.FromObject(value).WriteTo(writer);
}

但是,這會重置序列化設置,例如駱駝箱屬性命名。 我也嘗試過忽略Json.Net設置中的循環引用,但是那時沒有序列化任何轉換。

該錯誤所指的“自引用循環”是您的轉換器調用自身。 串行器的設置可使其直接使用您的轉換器。 您的轉換器調用JObject.FromObject() ,並傳入序列化程序。 JObject.FromObject使用序列化程序來嘗試從您的模型創建JObject 然后,串行器再次調用您的轉換器,依此類推。 Json.Net檢測到此遞歸循環並引發異常。

一種可能的解決方案是使用新的序列化程序實例,從原始序列化程序復制所有設置,但轉換器除外:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    JsonSerializer ser2 = new JsonSerializer();
    foreach (PropertyInfo prop in typeof(JsonSerializer).GetProperties()
            .Where(p => p.Name != nameof(JsonSerializer.Converters)))
    {
        prop.SetValue(ser2, prop.GetValue(serializer));
    }
    JObject.FromObject(value, ser2).WriteTo(writer);
}

但是,由於您的WriteJson方法似乎不執行任何操作,而只是加載對象並立即將其寫出而沒有任何更改,因此,更好的解決方案是簡單地重寫CanWrite以返回false。 然后, WriteJson不會調用WriteJson ,而將使用默認的序列化,無論如何,這似乎是您想要發生的事情。

public override bool CanWrite
{
    get { return false; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM