为什么Json.NET序列化[Serializable接口]和内部的只读属性的lambda失败? [英] Why does Json.NET serialization fail with [Serializable] and a lambda inside a read-only property?
问题描述
据<一href="http://james.newtonking.com/archive/2012/04/11/json-net-4-5-release-2-serializable-support-and-bug-fixes.aspx"相对=nofollow>本发行说明,Json.NET现在支持SerializableAttribute:
Json.NET现在检测具有SerializableAttribute类型和序列化该类型公共和私人所有的领域,而忽略属性。
我有下面的示例code,它抛出一个 JsonSerializationException
:
错误获取的价值CS $&LT;> 9__CachedAnonymousMethodDelegate1上 ConsoleApplication1.MyType。
如果我评论的TotalWithLambda属性,那么序列化成功的预期。事实上,我得到如下结果:
- 将[Serializable接口],离开TotalWithLambda:抛出JsonSerializationException
- 将[Serializable接口],删除TotalWithLambda:连载myList上唯一
- 删除[可序列化],离开TotalWithLambda:连载myList上,全面和TotalWithLambda
- 删除[可序列化],删除TotalWithLambda:连载myList上和总
我明白所有这些情况下,除了第一个。为什么对[Serializable接口]和只读的,在它的lambda物业组合导致此异常?
命名空间ConsoleApplication1
{
使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用Newtonsoft.Json;
类节目
{
静态无效的主要(字串[] args)
{
无功富=新的MyType();
foo.myList =新的名单,其中,INT&GT;(){0,1,2,3};
VAR returnVal = JsonConvert.SerializeObject(富);
Console.WriteLine(返回+ returnVal.ToString());
Console.ReadKey();
}
}
[可序列化]
一流的MyType
{
公众的IList&LT; INT&GT; myList中;
公众诠释共{{返回this.myList.Sum(); }}
公众诠释TotalWithLambda {{返回this.myList.Sum(X =&GT; X); }}
}
}
解决方案
我安装和使用
公共类的MyType
{
[编译器生成]
私有静态函数功能:LT; INT,INT&GT; CS $&LT;&GT; 9__CachedAnonymousMethodDelegate1;
[编译器生成]
私有静态诠释&LT; get_TotalWithLambda&GT; b__0(INT X){...}
// ...加上其他类会员...
}
在类有SerializableAttribute就可以了,Json.NET尝试将私有字段序列化,但不能因为它是类型 Func键&LT; INT,INT&GT;
。除去SerializableAttribute指示Json.NET忽略私有字段和,因此它不会引起问题。
更新: Json.NET 4.5版本3使得现在这只是一个问题,如果你明确地设置 IgnoreSerializableAttribute = FALSE
,也可以解决通过添加 JsonObjectAttribute
的类。
According to these release notes, Json.NET now supports the SerializableAttribute:
Json.NET now detects types that have the SerializableAttribute and serializes all the fields on that type, both public and private, and ignores the properties.
I have the following sample code that throws a JsonSerializationException
:
Error getting value from 'CS$<>9__CachedAnonymousMethodDelegate1' on 'ConsoleApplication1.MyType'.
If I comment the TotalWithLambda property, then the serialization succeeds as expected. In fact, I get the following results:
- Leave [Serializable], leave TotalWithLambda: throws JsonSerializationException
- Leave [Serializable], remove TotalWithLambda: serializes "myList" only
- Remove [Serializable], leave TotalWithLambda: serializes "myList", "Total", and "TotalWithLambda"
- Remove [Serializable], remove TotalWithLambda: serializes "myList" and "Total"
I understand all of these cases except the first one. Why does the combination of [Serializable] and a read-only property with a lambda in it cause this exception?
namespace ConsoleApplication1
{
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
class Program
{
static void Main(string[] args)
{
var foo = new MyType();
foo.myList = new List<int>() { 0, 1, 2, 3 };
var returnVal = JsonConvert.SerializeObject(foo);
Console.WriteLine("Return: " + returnVal.ToString());
Console.ReadKey();
}
}
[Serializable]
class MyType
{
public IList<int> myList;
public int Total { get { return this.myList.Sum(); } }
public int TotalWithLambda { get { return this.myList.Sum(x => x); } }
}
}
I installed and used JustDecompile and found that the compiler adds a field and a method to the class when the lambda is uncommented:
public class MyType
{
[CompilerGenerated]
private static Func<int, int> CS$<>9__CachedAnonymousMethodDelegate1;
[CompilerGenerated]
private static int <get_TotalWithLambda>b__0(int x) { ... }
// ... plus the other class members ...
}
When the class has SerializableAttribute on it, Json.NET tries to serialize the private field, but can't since it's of type Func<int, int>
. Removing the SerializableAttribute instructs Json.NET to ignore private fields and so it doesn't cause a problem.
Update: Json.NET 4.5 release 3 now makes this only a problem if you explicitly set IgnoreSerializableAttribute=false
, or it can be resolved by adding the JsonObjectAttribute
to the class..
这篇关于为什么Json.NET序列化[Serializable接口]和内部的只读属性的lambda失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!