2

.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 要求に基づいてプロパティを含めたり除外したりしたいことです。

逆シリアル化プロセスにフックして特定のプロパティをスキップする方法はありますか? ある種のカスタム契約を行うことはできますか?

4

1 に答える 1

6

DataContractSerializer(または、この場合は)を使用している場合は、クラスの装飾をDataContractJsonSerializer使用できます。DataMember(EmitDefaultValue = false)]このようにして、シリアル化したくないプロパティをデフォルト値(つまり、null文字列の場合、intの場合は0など)に設定できますが、シリアル化されません。

DataContractJsonSerializerASP.NET Web APIを使用している場合、デフォルトのJSONシリアライザーは(DCJS)ではなく、代わりにJSON.NETであることに注意してください。したがって、DCJSを使用するように明示的に構成しない限り、同じ動作( 、およびそのプロパティ)JsonMediaTypeFormatterを取得するには別の属性が必要です。JsonPropertyDefaultValueHandling

以下のコードは、両方のシリアライザーを使用して、このCarオブジェクトで割り当てられた2つのメンバーのみをシリアル化します。属性の1つだけを使用する場合は、属性の1つを削除できることに注意してください。

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 に答える