我正在尝试找到在我的.net WebApi项目中有条件地包含和删除我的datacontract序列化属性的最佳方法。在我的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请求包含和排除属性,而不一定是它们是否有数据。
有没有办法挂钩反序列化过程并跳过某些属性?我可以做某种定制合同吗?
答案 0 :(得分: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()));
}
}