JSON.NET 序列化失败

3

我有一个可以序列化为XML的LINQ-to-SQL对象。我可以调用Newtonsoft.Json.JsonConvert.SerializeObject()方法并获得JSON结果。当我将相同的结果作为WebAPI中的对象传递时,会出现错误(请参见下文)。我建立了一个跟踪编写器来捕获空内部异常路径,但如果路径是'',我不知道如何找出哪个项目导致错误?

20130301122959: Started serializing AnvilDB.Partner. Path ''.
20130301122959: Error serializing AnvilDB.Partner. An item with the same key has already been added. Path ''.
Error: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at System.Web.Http.Metadata.Providers.AssociatedMetadataProvider`1.CreateTypeInformation(Type type)
   at System.Web.Http.Metadata.Providers.AssociatedMetadataProvider`1.GetTypeInformation(Type type)
   at System.Web.Http.Metadata.Providers.AssociatedMetadataProvider`1.GetMetadataForProperty(Func`1 modelAccessor, Type containerType, String propertyName)
   at System.Web.Http.Validation.ModelValidationRequiredMemberSelector.IsRequiredMember(MemberInfo member)
   at System.Net.Http.Formatting.JsonContractResolver.ConfigureProperty(MemberInfo member, JsonProperty property)
   at System.Net.Http.Formatting.JsonContractResolver.CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateProperties(Type type, MemberSerialization memberSerialization)
   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract(Type objectType)
   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract(Type objectType)
   at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract(Type type)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
20130301123002: Started serializing System.Web.Http.HttpError. Path ''.
20130301123002: Started serializing System.Web.Http.HttpError. Path 'InnerException'.
20130301123002: Finished serializing System.Web.Http.HttpError. Path 'InnerException'.
20130301123002: Finished serializing System.Web.Http.HttpError. Path ''.
2个回答

6
挖掘一番后,我发现可以为序列化程序设置错误处理程序,然后检查ErrorContext.Member值。这指向一个XElement类型的属性。进一步搜索发现这是一个已知/报告的错误,但尚未修复;请参见https://github.com/JamesNK/Newtonsoft.Json/issues/53 总结:如果您具有空值的XElement属性,则JSON.NET会失败。
以下是我添加的内容以诊断根本原因:
    base.Configuration.Formatters.JsonFormatter.SerializerSettings.Error = (sender, args) =>
    {
        string e = string.Format("{0}: {1}", args.ErrorContext.Member, args.ErrorContext.Path, args.ErrorContext.Error.Message);
        myTracer.Trace(System.Diagnostics.TraceLevel.Error, e, args.ErrorContext.Error);
    };

myTracer是一个简单的文件跟踪写入器。


更新

我现在已经找到了解决这个错误的方法。

WebAPI用于序列化JSON对象的类并不直接来自于JSON.NET,而是设置为JsonContractResolver的一个实例,该实例位于System.Net.Http.Formatting中。幸运的是,这是开源的,因此您可以在此处查看当前版本:

http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/4764b0111b91#src/System.Net.Http.Formatting/Formatting/JsonContractResolver.cs

我将这段代码复制到自己的类中,并使用此代码(未更改)替换了JSON.NET中的Contract Resolver,问题得以解决。由此我得出结论:当前发布的WebAPI版本(System.Net.Http.Formatting版本4.0.20710.0)存在此错误,下一个版本可能会修复此问题。
如果您像我一样需要立即解决问题,请按以下步骤操作:
  1. 使用JsonContractResolver.cs代码创建自己的合同解析器类
  2. 更改启动配置以覆盖ContractResolver设置:

示例:

var settings = System.Web.Http.GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings; 
// create formatter 
var formatter = new System.Net.Http.Formatting.JsonMediaTypeFormatter(); 
settings.ContractResolver = new MyJsonContractResolver(formatter);

这应该有所帮助。


0
这看起来像是Web API的一个bug。我建议在这里提交一个关于它的bug报告:

http://aspnetwebstack.codeplex.com/workitem/list/basic

同时,我认为您可以通过以下设置配置来解决此问题:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();

谢谢。看看我的结果 - 有一个错误,但它在JSON.NET中而不是WebAPI中。 - Quango

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接