2

我正在尝试在我的 .net WebApi 项目中找到有条件地从我的数据合同序列化中包含和删除属性的最佳方法。在我的 Api 中,我希望允许用户指定他们想要返回的字段。

例如,假设我希望我的 API 返回以下类的实例。

public class Car
{
    public int Id { get; set; }
    public string Year { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public string Color { get; set; }
}

但是,API 调用不是请求整个对象,而是只需要 Id 和 Make 字段。所以返回 JSON 将是

 { "Id": 12345, "Make": "Ford"}

而不是整个对象。

DataContract Serializer 有没有一种方法可以有条件地从返回对象中添加和删除属性?

**编辑我查看了 IgnoreDefault 属性,但我不相信它会完全满足我的需要。问题是我想根据 api 请求包含和排除属性,不一定取决于它们是否有数据。

有什么方法可以挂钩反序列化过程并跳过某些属性?我可以做某种定制合同吗?

4

1 回答 1

6

如果您使用的是DataContractSerializer(或在本例中为DataContractJsonSerializer),则可以DataMember(EmitDefaultValue = false)]在您的班级中使用装饰。这样,您可以将希望序列化的属性设置为它们的默认值(即,null对于字符串,0 表示整数等),它们不会被序列化。

如果您使用的是 ASP.NET Web API,那么您应该知道默认的 JSON 序列化程序不是DataContractJsonSerializer(DCJS),而是 JSON.NET。因此,除非您明确配置您JsonMediaTypeFormatter使用 DCJS,否则您需要另一个属性来获得相同的行为(JsonProperty及其DefaultValueHandling属性)。

下面的代码仅使用两个序列化器序列化在此 Car 对象中分配的两个成员。请注意,如果您只打算使用其中一个属性,则可以删除其中一个属性。

public class StackOverflow_12465285
{
    [DataContract]
    public class Car
    {
        private int savedId;
        private string savedYear;
        private string savedMake;
        private string savedModel;
        private string savedColor;

        [DataMember(EmitDefaultValue = false)]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
        public int Id { get; set; }
        [DataMember(EmitDefaultValue = false)]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
        public string Year { get; set; }
        [DataMember(EmitDefaultValue = false)]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
        public string Make { get; set; }
        [DataMember(EmitDefaultValue = false)]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
        public string Model { get; set; }
        [DataMember(EmitDefaultValue = false)]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
        public string Color { get; set; }

        [OnSerializing]
        void OnSerializing(StreamingContext ctx)
        {
            this.savedId = this.Id;
            this.savedYear = this.Year;
            this.savedMake = this.Make;
            this.savedModel = this.Model;
            this.savedColor = this.Color;

            // Logic to determine which ones to serialize, let's say I only want Id, Make; so make all others default.
            this.Color = default(string);
            this.Model = default(string);
            this.Year = default(string);
        }

        [OnSerialized]
        void OnSerialized(StreamingContext ctx)
        {
            this.Id = this.savedId;
            this.Year = this.savedYear;
            this.Make = this.savedMake;
            this.Model = this.savedModel;
            this.Color = this.savedColor;
        }
    }

    public static void Test()
    {
        Car car = new Car { Id = 12345, Make = "Ford", Model = "Focus", Color = "Red", Year = "2010" };
        JsonSerializer js = new JsonSerializer();
        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);
        js.Serialize(sw, car);
        Console.WriteLine("Using JSON.NET: {0}", sb.ToString());

        MemoryStream ms = new MemoryStream();
        DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(Car));
        dcjs.WriteObject(ms, car);
        Console.WriteLine("Using DCJS: {0}", Encoding.UTF8.GetString(ms.ToArray()));
    }
}
于 2012-09-17T19:18:33.970 回答