1. ホーム
  2. c#

[解決済み] json.netでプロパティをデシリアライズし、シリアライズしないようにする

2022-04-26 16:02:38

質問

Json.netでC#オブジェクトをシリアライズして生成された設定ファイルがあります。

シリアライズされたクラスの1つのプロパティを、単純なenumプロパティからクラスプロパティに移行したいと思います。

これを行う簡単な方法の1つは、クラスの古いenumプロパティを残して、Json.netが設定を読み込むときにこのプロパティを読み込むように手配し、次にオブジェクトをシリアライズするときにそれを再び保存しないようにすることでしょう。 古いenumから新しいクラスを生成することは、別途対処することにします。

C#オブジェクトのプロパティをマークして(例えば属性で)、Json.netがシリアライズ時にのみそれを無視し、デシリアライズ時にはそれに注目するような、簡単な方法はありますか?

どのように解決するのですか?

実は、望む結果を得るためには、かなりシンプルな方法がいくつかあります。

例えば、現在、クラスがこのように定義されているとします。

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メソッドの追加

Json.NETには、プロパティを条件付きでシリアライズする機能があり、その際、対応する ShouldSerialize のメソッドを使用します。

この機能を使用するには、ブール値の ShouldSerializeBlah() メソッドを作成し、そこで Blah は、シリアライズしたくないプロパティの名前に置き換えてください。 このメソッドの実装は、常に false .

class Config
{
    public Fizz ObsoleteSetting { get; set; }

    public Bang ReplacementSetting { get; set; }

    public bool ShouldSerializeObsoleteSetting()
    {
        return false;
    }
}

注意: この方法が好きだけれども、クラスのパブリックなインターフェースを ShouldSerialize メソッドを使用することができます。 IContractResolver を使えば、プログラム的に同じことができます。 参照 条件付きプロパティシリアライズ のドキュメントを参照してください。

アプローチ2:JObjectでJSONを操作する

を使う代わりに JsonConvert.SerializeObject を使用してシリアライズを行うには、設定オブジェクトを JObject そして、書き出す前にJSONから不要なプロパティを削除するだけです。 ほんの2、3行の追加コードです。

JObject jo = JObject.FromObject(config);

// remove the "ObsoleteSetting" JProperty from its parent
jo["ObsoleteSetting"].Parent.Remove();

json = jo.ToString();

アプローチ3:属性の巧みな(ab)使用

  1. を適用する。 [JsonIgnore] 属性を、シリアライズさせたくないプロパティに設定します。
  2. 代替を追加します。 プライベート プロパティ・セッターを、元のプロパティと同じ型のクラスに追加します。 そのプロパティの実装が元のプロパティを設定するようにする。
  3. を適用します。 [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; }
}