Json.net を使用して C# オブジェクトをシリアル化することによって生成された構成ファイルがいくつかあります。
シリアル化されたクラスの 1 つのプロパティを、単純な列挙型プロパティからクラス プロパティに移行したいと考えています。
これを実行する簡単な方法の 1 つは、クラスに古い enum プロパティを残し、構成をロードするときに Json.net がこのプロパティを読み取るように設定し、次にオブジェクトをシリアル化するときに再度保存しないようにすることです。古い enum から新しいクラスを生成する処理は別途行います。
C# オブジェクトのプロパティを (たとえば属性を使用して) マークして、Json.net がシリアル化時にのみそれを無視し、デシリアル化時にそれを考慮するようにする簡単な方法はありますか?
ベストアンサー1
実際に、望む結果を達成するために使用できるかなりシンプルなアプローチがいくつかあります。
たとえば、クラスが現在次のように定義されているとします。
class Config
{
public Fizz ObsoleteSetting { get; set; }
public Bang ReplacementSetting { get; set; }
}
enum Fizz { Alpha, Beta, Gamma }
class Bang
{
public string Value { get; set; }
}
そして、次のことを行いたいとします:
string json = @"{ ""ObsoleteSetting"" : ""Gamma"" }";
// deserialize
Config config = JsonConvert.DeserializeObject<Config>(json);
// migrate
config.ReplacementSetting =
new Bang { Value = config.ObsoleteSetting.ToString() };
// serialize
json = JsonConvert.SerializeObject(config);
Console.WriteLine(json);
これを取得するには:
{"ReplacementSetting":{"Value":"Gamma"}}
アプローチ1: ShouldSerializeメソッドを追加する
ShouldSerialize
Json.NETには、クラス内の対応するメソッドを検索して、プロパティを条件付きでシリアル化する機能があります。
この機能を使用するには、をシリアル化しないプロパティの名前に置き換えたブール型ShouldSerializeBlah()
メソッドをクラスに追加します。このメソッドの実装が常に を返すようにします。Blah
false
class Config
{
public Fizz ObsoleteSetting { get; set; }
public Bang ReplacementSetting { get; set; }
public bool ShouldSerializeObsoleteSetting()
{
return false;
}
}
注: このアプローチが気に入っているが、メソッドを導入することでクラスのパブリックインターフェースを混乱させたくない場合はShouldSerialize
、を使用してIContractResolver
プログラム的に同じことを行うことができます。条件付きプロパティのシリアル化ドキュメントに記載されています。
アプローチ 2: JObjects を使用して JSON を操作する
を使用してシリアル化を行う代わりにJsonConvert.SerializeObject
、 に config オブジェクトをロードしJObject
、書き出す前に JSON から不要なプロパティを削除するだけです。これは、ほんの数行のコードを追加するだけです。
JObject jo = JObject.FromObject(config);
// remove the "ObsoleteSetting" JProperty from its parent
jo["ObsoleteSetting"].Parent.Remove();
json = jo.ToString();
アプローチ3: 属性の巧妙な(悪用)使用
[JsonIgnore]
シリアル化したくないプロパティに属性を適用します。- 代替案を追加し、プライベート元のプロパティと同じ型のクラスにプロパティ セッターを追加します。そのプロパティの実装を元のプロパティに設定します。
[JsonProperty]
代替セッターに属性を適用し、元のプロパティと同じ JSON 名を指定します。
修正されたクラスは次のとおりですConfig
。
class Config
{
[JsonIgnore]
public Fizz ObsoleteSetting { get; set; }
[JsonProperty("ObsoleteSetting")]
private Fizz ObsoleteSettingAlternateSetter
{
// get is intentionally omitted here
set { ObsoleteSetting = value; }
}
public Bang ReplacementSetting { get; set; }
}