为什么Json.NET序列化[Serializable接口]和内部的只读属性的lambda失败? [英] Why does Json.NET serialization fail with [Serializable] and a lambda inside a read-only property?

查看:123
本文介绍了为什么Json.NET序列化[Serializable接口]和内部的只读属性的lambda失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据<一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现在检测具有Seri​​alizableAttribute类型和序列化该类型公共和私人所有的领域,而忽略属性。

我有下面的示例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); }}
    }

}
 

解决方案

我安装和使用

JustDecompile < /一>并且发现该编译器添加一个字段和方法的类时的λ是未注释:

 公共类的MyType
{
    [编译器生成]
    私有静态函数功能:LT; INT,INT&GT; CS $&LT;&GT; 9__CachedAnonymousMethodDelegate1;

    [编译器生成]
    私有静态诠释&LT; get_TotalWithLambda&GT; b__0(INT X){...}

    // ...加上其他类会员...
}
 

在类有Seri​​alizableAttribute就可以了,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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆