为什么Json.NET序列化在[Serializable]和一个只读属性中的lambda失败?

时间:2012-04-13 15:08:15

标签: exception serialization .net-4.0 json.net

根据these release notes,Json.NET现在支持SerializableAttribute:

  

Json.NET现在检测具有Seri​​alizableAttribute的类型,并序列化该类型的所有字段,包括公共字段和私有字段,并忽略属性。

我有以下示例代码抛出JsonSerializationException

  

从“CS $<> 9__CachedAnonymousMethodDelegate1”获取值时出错   'ConsoleApplication1.MyType'。

如果我评论TotalWithLambda属性,则序列化按预期成功。事实上,我得到以下结果:

  • 保留[Serializable],离开TotalWithLambda:抛出JsonSerializationException
  • 保留[Serializable],删除TotalWithLambda:仅序列化“myList”
  • 删除[Serializable],离开TotalWithLambda:序列化“myList”,“Total”和“TotalWithLambda”
  • 删除[Serializable],删除TotalWithLambda:序列化“myList”和“Total”

除了第一个案例外,我理解所有这些案件。为什么[Serializable]和带有lambda的只读属性的组合会导致此异常?

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

}

2 个答案:

答案 0 :(得分:3)

我安装并使用了JustDecompile,发现当lambda取消注释时,编译器会向该类添加一个字段和一个方法:

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

当类上有Seri​​alizableAttribute时,Json.NET会尝试序列化私有字段,但不能,因为它的类型为Func<int, int>。删除SerializableAttribute指示Json.NET忽略私有字段,因此不会导致问题。

更新:如果您明确设置IgnoreSerializableAttribute=false,Json.NET 4.5版本3现在只会出现问题,或者可以通过将JsonObjectAttribute添加到班级来解决此问题..

答案 1 :(得分:2)

默认情况下,我在版本3中将IgnoreSerializableAttribute更改为true,从而撤消了第2版中引入的重大更改 - http://json.codeplex.com/releases/view/85975

您可以在此处阅读更多相关信息 - http://json.codeplex.com/discussions/351981