Why does Json.NET serialization fail with [Serializable] and a lambda inside a read-only property?

.net-4.0, exception, json.net, serialization

Solution

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

Problem

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

Original source