【问题标题】:JSON.NET serialization failureJSON.NET 序列化失败
【发布时间】:2013-03-01 12:44:27
【问题描述】:

我有一个可以毫无问题地序列化为 XML 的 LINQ-to-SQL 对象。我可以调用 Newtonsoft.Json.JsonConvert.SerializeObject() 并得到 JSON 结果。当我在 WebAPI 中传递与对象相同的结果时,我得到一个错误(见下文)。我构建了一个跟踪编写器来捕获 null 内部异常路径,如果路径是 '',我不确定如何找出导致错误的项目?

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 ''.

【问题讨论】:

    标签: serialization asp.net-web-api json.net


    【解决方案1】:

    四处挖掘我发现我可以为序列化程序设置一个错误处理程序,然后检查 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)存在bug,下个版本大概会修复这个问题。

    如果你像我一样需要现在修复它,这里是步骤:

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

    这应该会有所帮助。

    【讨论】:

      【解决方案2】:

      这看起来像是 Web API 中的错误。我建议在这里提交一个关于它的错误:

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

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

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

      【讨论】:

      • 谢谢 .. 看看我自己的结果 - 有一个错误,但它在 JSON.NET 中而不是在 WebAPI 中。
      猜你喜欢
      • 2012-06-20
      • 2015-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-27
      相关资源
      最近更新 更多