ASP.NET WebAPI(逆)シーケンス化[SerializableAttribute]で修飾されたクラスのピット
3088 ワード
問題を発見する
ASP.NET WebAPIプロジェクトには、このようなViewModelクラスがあります.
[Serializable]
class Product
{
public int Id { get; set; }
public decimal Price { get; set; }
public DateTime ProductDate { get; set; }
}
ControllerとActionコードは次のとおりです.
public class ProductController : ApiController
{
public Product Get(int id)
{
return new Product()
{
Id = 1,
Price = 12.9m,
ProductDate = new DateTime(1992, 1, 1)
};
}
}
クライアントはこのリソースを要求した:
http://localhost:5000/api/product/1
、その結果、WebAPIは次のようなJSONを返すことが分かった.{
"k__BackingField": 1,
"k__BackingField": 12.9,
"k__BackingField": "1992-01-01T00:00:00"
}
自動プロパティにはフィールドが定義されていませんが、C#コンパイラは
private int k__BackingField
のような対応するプライベートフィールドを生成します.WebAPIのシーケンス化では属性名をJSONのキーとして使用することを期待していますが、ここでWebAPIのシーケンス化はコンパイラが生成したプライベートフィールドであり、明らかに私たちの要求に合致しません.変なところは、Jsonを単独で使うと.NETクラスライブラリをシーケンス化すると、期待されるJSONが得られ、以下のようになる.
{
"Id": 1,
"Price": 12.9,
"ProductDate": "1992-01-01T00:00:00"
}
原因を見つける
Googleを経て、SerializableAttributeと関係があった.JsonからNET 4.5 Release 2のリリースが始まり、このような機能が追加されました.
タイプにSerializableAttributeがあることが検出された場合、そのタイプのすべてのプライベート/公開フィールドがシーケンス化され、そのプロパティは無視されます.この新しいプロパティが不要な場合は、クラスにJsonObjectAttributeを適用して上書きするか、D e f a u l t ContractResolverのI g n o r e SerializableAttributeをグローバル範囲でtrueに設定します.release 3のバージョンからI g n o r e SerializableAttributeのデフォルトはtrueです.
ASP.NET WebAPIはJsonに依存する.NETは、IgnoreSerializableAttributeをfalseに設定します.つまり、SerializableAttributeを無視しないため、クラスが[SerializableAttribute]で修飾されると、シーケンス化されたフィールドのみが属性を無視し、自動属性を使用するとコンパイラが自動的に生成するフィールド名が出力されます.
問題を解決する
問題の原因を理解したら、以下の方法で解決できます.
最も簡単な方法は[Serializable]を取り除くことであり,何らかの理由で取り除くことができなければ,他の2つの方法を用いることができる.
JsonObjectAttributeの適用
[Newtonsoft.Json.JsonObject]
[System.Serializable]
class Product
{
public int Id { get; set; }
public decimal Price { get; set; }
public DateTime ProductDate { get; set; }
}
I g n o r e SerializableAttributeの設定
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// .........
// SerializerSettings IgnoreSerializableAttribute = true
config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings();
}
}
参考:Json.NET 4.5 Release 2 – Serializable support and bug fixesWhy won't Web API deserialize this but JSON.Net will?
転載先:https://www.cnblogs.com/songxingzheng/p/6482431.html