By default, Json.NET ignores the Serializable
attribute. However, according to a comment to this answer by Maggie Ying (quoted below because comments are not meant to last), WebAPI overrides that behavior, which causes your output.
Json.NET serializer by default set the IgnoreSerializableAttribute to true. In WebAPI, we set that to false. The reason why you hit this issue is because Json.NET ignores properties: "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" (quoted from james.newtonking.com/archive/2012/04/11/…)
A simple example that demonstrates the same behavior without WebAPI can look like this:
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
namespace Scratch
{
[Serializable]
class Foo
{
public string Bar { get; set; }
}
class Program
{
static void Main()
{
var foo = new Foo() { Bar = "Blah" };
Console.WriteLine(JsonConvert.SerializeObject(foo, new JsonSerializerSettings()
{
ContractResolver = new DefaultContractResolver()
{
IgnoreSerializableAttribute = false
}
}));
}
}
}
There are several ways around this behavior. One is to decorate your model with a plain JsonObject
attribute:
[Serializable]
[JsonObject]
class Foo
{
public string Bar { get; set; }
}
Another way is to override the default settings in your Application_Start()
. According to this answer, the default settings should do it:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings();
If that doesn't work, you could be explicit about it:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings()
{
ContractResolver = new DefaultContractResolver()
{
IgnoreSerializableAttribute = true
}
};
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings();
so as not to have to decorate every single model with[JsonObject]
– Radar