【问题标题】:JSon.Net Serialize result of yield returnJSon.Net序列化收益率返回结果
【发布时间】:2013-04-07 19:41:19
【问题描述】:

我正在尝试使用 json 和 JSon.Net 库将一些数据返回到 Web 服务。我的一个函数是一个迭代器方法,它使用 yield return 列出数据。当我尝试序列化这个返回值时,我得到一个无效的操作异常

我正在使用 string jsonEncoded = JsonConvert.SerializeObject(ret, Formatting.Indented); 序列化返回值。

异常的完整堆栈跟踪是:

System.InvalidOperationException: This operation is only valid on generic types.
   at System.RuntimeType.GetGenericTypeDefinition()
   at Newtonsoft.Json.Serialization.JsonArrayContract..ctor(Type underlyingType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonArrayContract.cs:line 148
   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateArrayContract(Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\DefaultContractResolver.cs:line 686
   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract(Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\DefaultContractResolver.cs:line 800
   at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract(Type type) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\DefaultContractResolver.cs:line 232
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.GetContractSafe(Object value) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalWriter.cs:line 83
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalWriter.cs:line 67
   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonSerializer.cs:line 753
   at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value, Type objectType) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonSerializer.cs:line 668
   at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Type type, Formatting formatting, JsonSerializerSettings settings) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonConvert.cs:line 921
   at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Formatting formatting, JsonSerializerSettings settings) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonConvert.cs:line 893
   at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Formatting formatting) in c:\Temp\Json\Working\Newtonsoft.Json\Src\Newtonsoft.Json\JsonConvert.cs:line 837
   at AladdinWeb.Handlers.AladdinHandler.ProcessRequest(HttpContext context) in C:\Users\mehrlich\Projects\AladdinWeb\AladdinWeb\Server\Handlers\AladdinHandler.cs:line 85 [ 15/04/2013 11:24:24.68135 ]

迭代器方法的签名是:

public IEnumerable<dynamic> FunctionName() { ... }

到目前为止,我有一个临时解决方案,方法是检查对该函数的调用并在返回值上调用 ToList。这可以很好地序列化,但它是一种丑陋的解决方案,因为我需要为它提供一个特殊情况(以及我可能添加的任何其他迭代器方法)。我的猜测是,这与未枚举的 IEnumerable 有关。

我可以让 Json.Net 序列化我的迭代器函数的结果,还是我总是需要这样的特殊情况?如果需要更多信息或源代码,请告诉我,我会发布。

更多信息:我正在使用 .Net 框架 4.0 版,我正在使用 Json.Net 5.0r2 版

迭代器方法的精简源代码

public IEnumerable<dynamic> FunctionName()
{
    var methodList = typeof(Targets).GetMethods();

    foreach (var m in methodList)
    {
        dynamic info = new ExpandoObject();

        info.Name = m.Name;

        info.Parameters = from param in m.GetParameters()
                                  select param.Name;

        yield return info;
    }
}

方法调用源码

...
object ret = null;
if (q == "FunctionName")
{
    ret = FunctionName();  // This causes an exception to be thrown later
    // ret = FunctionName().ToList(); // This does NOT throw an exception later
}
else
{
    ret = DoOtherStuff(q, request);
}

// Serialize the result to JSON 
// This line throws the exception
string jsonEncoded = JsonConvert.SerializeObject(ret, Formatting.Indented);
...

【问题讨论】:

  • 我不确定您是否可以在该类型的迭代器方法上调用 serialise。你不知道 FunctionName 在编译时返回的类型吗?还调用 ToList() 我假设您然后转换为特定类型?
  • stackoverflow.com/questions/5156664/… - JSON.Net 处理动态对象可能只是个问题;可以将它们展平为字典,此时您的问题可能会消失。
  • @TheKingDave 你的意思是我不能序列化IEnumerable&lt;dynamic&gt;?我也尝试将函数更改为IEnumerable&lt;ExpandoObject&gt;,但它没有改变任何东西。至于第二部分,不,我不是演员,我只是打电话给object ret = FunctionName().ToList()
  • 序列化yield return-created IEnumerable&lt;dynamic&gt; 似乎对我有用。您能否包含显示您的问题的完整(但简短)代码?另外,您使用的是什么版本的 JSON.NET?
  • 那么正如你所说的 JSON.Net 没有枚举,因为这是一个迭代器方法。如果你在你的方法中设置了一个断点,当你不使用 ToList() 时,它是否会像你期望的那样被调用?

标签: c# json json.net ienumerable yield-return


【解决方案1】:

这个问题是 JSon.Net 5.0r2 版本的一个错误,更新到 5.0r3 将解决这个问题,事实上这是 5.0r3 版本的唯一原因。

【讨论】:

  • 谢谢!我正在从 EPiServer 安装一个 nuget 提要,并且在很长一段时间内一直在努力找出 nuget 包有什么问题,因为突然我的应用程序显示了上面报告的错误!我终于发现它的依赖项之一是 Newtonsoft.Json 5.0.1,所以它最终升级到这个版本,因此得到了这个错误。我试过你的建议,现在可以了。谢谢一百万!
猜你喜欢
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
相关资源
最近更新 更多