在WebAPI中使用Model上的Serializable属性

Ebb*_*bbs 13 c# json serializable asp.net-web-api

我有以下场景:我正在使用WebAPI并根据模型将JSON结果返回给使用者.我现在还需要将模型序列化为base64,以便能够将它们保存在缓存中和/或将它们用于审计目的.问题是当我将[Serializable]属性添加到模型以便将模型转换为Base64时,JSON输出会发生如下变化:

该模型:

[Serializable]
public class ResortModel
{
    public int ResortKey { get; set; }

    public string ResortName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如果没有该[Serializable]属性,则JSON输出为:

{
    "ResortKey": 1,
    "ResortName": "Resort A"
}
Run Code Online (Sandbox Code Playgroud)

使用[Serializable]JSON输出的属性是:

{
    "<ResortKey>k__BackingField": 1,
    "<ResortName>k__BackingField": "Resort A"
}
Run Code Online (Sandbox Code Playgroud)

如何在[Serializable]不更改JSON输出的情况下使用该属性?

Bar*_*rop 31

默认情况下,Json.NET忽略该Serializable属性.不过,根据要评论此答案张曼玉颖(以下引用,因为意见并非持续)的WebAPI覆盖这种行为,这会导致你的输出.

默认情况下,Json.NET序列化程序将IgnoreSerializableAttribute设置为true.在WebAPI中,我们将其设置为false.您遇到此问题的原因是因为Json.NET忽略了属性:"Json.NET现在检测具有Seri​​alizableAttribute的类型并序列化该类型的所有字段,包括公共和私有,并忽略属性"(引自james. newtonking.com/archive/2012/04/11/...)

在没有WebAPI的情况下演示相同行为的简单示例可能如下所示:

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
                    }
                }));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有几种方法可以解决此问题.一种是用普通JsonObject属性装饰你的模型:

[Serializable]
[JsonObject]
class Foo
{
    public string Bar { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是覆盖你的默认设置Application_Start().根据这个答案,默认设置应该这样做:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings();
Run Code Online (Sandbox Code Playgroud)

如果这不起作用,你可以明确它:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings()
    {
        ContractResolver = new DefaultContractResolver()
        {
            IgnoreSerializableAttribute = true
        }
    };
Run Code Online (Sandbox Code Playgroud)

  • 谢谢Bart,好答案!我使用了GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings();,这样就不必用[JsonObject]装饰每个模型。 (2认同)