web-dev-qa-db-ja.com

WebAPIのモデルでSerializable属性を使用する

次のシナリオがあります。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]属性を使用するにはどうすればよいですか?

13
Ebbs

デフォルトでは、Json.NETはSerializable属性を無視します。ただし、 この回答 by Maggie Ying (コメントは長続きしないため、以下に引用)へのコメントによると、WebAPIはその動作をオーバーライドし、出力を引き起こします。

Json.NETシリアライザーは、デフォルトでIgnoreSerializableAttributeをtrueに設定します。 WebAPIでは、これをfalseに設定します。この問題が発生する理由は、Json.NETがプロパティを無視するためです。「Json.NETはSerializableAttributeを持つ型を検出し、パブリックとプライベートの両方でその型のすべてのフィールドをシリアル化し、プロパティを無視するようになりました」(-から引用) james.newtonking.com/archive/2012/04/11/…

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
                    }
                }));
        }
    }
}
_

この動作にはいくつかの方法があります。 1つは、単純なJsonObject属性でモデルを装飾することです。

_[Serializable]
[JsonObject]
class Foo
{
    public string Bar { get; set; }
}
_

もう1つの方法は、Application_Start()のデフォルト設定を上書きすることです。 この回答 によると、デフォルト設定はそれを行う必要があります:

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

それが機能しない場合は、それについて明示することができます。

_GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings()
    {
        ContractResolver = new DefaultContractResolver()
        {
            IgnoreSerializableAttribute = true
        }
    };
_
32
Bart van Nierop