我有一个由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);
}
方法的实现是:
Startup.ConfigureServices
自定义转换器在ASP.NET Core API应用程序中使用,并添加到services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.Converters.Add(new TransformationConverter());
});
方法中的服务中,如下所示:
TransformationPlanModel
当Newtonsoft.Json.JsonSerializationException
作为来自API端点的响应返回并被序列化时,会抛出JObject.FromObject
,其中包含以下消息:“使用类型'(...)检测到自引用循环.RemoveRowsTransformationModel “”。是什么导致这个例外?我没有看到自引用循环的位置。我不知道它是否重要,但我使用的是.NET Core 2.0 Preview 1。
有趣的是,当WriteJson
方法中使用不带序列化参数的public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject.FromObject(value).WriteTo(writer);
}
重载时,它可以正常工作:
{{1}}
然而,这会重置序列化设置,例如camel case属性命名。我也尝试忽略Json.Net设置中的循环引用,但是当时没有转换序列化。
答案 0 :(得分:4)
在这种情况下,错误所指的“自引用循环”是您的转换器调用自身。串行器具有指示它使用转换器的设置。您的转换器调用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
,而是使用默认序列化,这似乎就是你想要在这里发生的事情。
public override bool CanWrite
{
get { return false; }
}