【发布时间】: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<dynamic>?我也尝试将函数更改为IEnumerable<ExpandoObject>,但它没有改变任何东西。至于第二部分,不,我不是演员,我只是打电话给object ret = FunctionName().ToList() -
序列化
yield return-createdIEnumerable<dynamic>似乎对我有用。您能否包含显示您的问题的完整(但简短)代码?另外,您使用的是什么版本的 JSON.NET? -
那么正如你所说的 JSON.Net 没有枚举,因为这是一个迭代器方法。如果你在你的方法中设置了一个断点,当你不使用 ToList() 时,它是否会像你期望的那样被调用?
标签: c# json json.net ienumerable yield-return