在 WebAPI 中的 Model 上使用 Serializable 属性

Posted

技术标签:

【中文标题】在 WebAPI 中的 Model 上使用 Serializable 属性【英文标题】:Using Serializable attribute on Model in WebAPI 【发布时间】:2015-07-09 19:40:32 【问题描述】:

我有以下场景:我正在使用 WebAPI 并基于模型将 JSON 结果返回给消费者。我现在有额外的要求将模型序列化为 base64,以便能够将它们保存在缓存中和/或将它们用于审计目的。问题是当我将[Serializable] 属性添加到模型以便将模型转换为Base64 时,JSON 输出更改如下:

模型:

[Serializable]
public class ResortModel

    public int ResortKey  get; set; 

    public string ResortName  get; set; 

如果没有 [Serializable] 属性,JSON 输出是:


    "ResortKey": 1,
    "ResortName": "Resort A"

使用[Serializable] 属性,JSON 输出为:


    "<ResortKey>k__BackingField": 1,
    "<ResortName>k__BackingField": "Resort A"

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

【问题讨论】:

【参考方案1】:

默认情况下,Json.NET 忽略 Serializable 属性。但是,根据Maggie Ying 对this answer 的评论(下面引用,因为 cmets 并不意味着持久),WebAPI 会覆盖该行为,从而导致您的输出。

Json.NET 序列化程序默认将 IgnoreSerializableAttribute 设置为 true。在 WebAPI 中,我们将其设置为 false。您遇到此问题的原因是因为 Json.NET 忽略了属性:“Json.NET 现在检测具有 SerializableAttribute 的类型并序列化该类型的所有字段,包括公共和私有,并忽略属性”(引自 @987654323 @)

在没有 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
                    
                ));
        
    

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

[Serializable]
[JsonObject]
class Foo

    public string Bar  get; set; 

另一种方法是覆盖 Application_Start() 中的默认设置。根据this answer,默认设置应该是这样做的:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings();

如果这不起作用,您可以明确说明:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings()
    
        ContractResolver = new DefaultContractResolver()
        
            IgnoreSerializableAttribute = true
        
    ;

【讨论】:

谢谢巴特,很好的回答!我选择使用GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new Newtonsoft.Json.JsonSerializerSettings();,以便不必用[JsonObject]装饰每个模型

以上是关于在 WebAPI 中的 Model 上使用 Serializable 属性的主要内容,如果未能解决你的问题,请参考以下文章

model validation for webapi

具有外部和内部端点的 Service Fabric Web Api

.NET Core WebAPI - 带有属性路由的 404 回退

WebAPI 2 中的 DefaultInlineConstraintResolver 错误

POST json-server 中的对象集合

实体框架 - 基础提供程序在 ConnectionString 上失败