72681
### 要点

System.Text.Jsonで、特定のプロパティについて読み込みはできるが書き込みはできないようにしたい

### 目的

System.Text.Jsonでアプリの保存データを作成しようと考えています。

アプリのバージョンアップによりフォーマットが変化しプロパティの一部が不要になることが想定されます。互換性維持のためそのプロパティは読み込みはできるようにしておきたいですが、新しいバージョンの保存データには出力したくありません。これを実現させるためのスマートな方法はありますでしょうか。

これまでは DataContract を使用して保存データを運用しており、`[DataMember(EmitDefaultValue=false)]`
属性を使用してこれを実現していました。

### 環境

  * .NET Framework 4.7.2
  * System.Text.Json 4.7.1
CC BY-SA 4.0
2020-03-18T04:27:12.343
63954
2020-12-16T03:31:52.577
14817
question
c# .net
System.Text.Jsonで特定のプロパティを書き込みだけ無効にしたい
これのどれか(2番目かな？)が使えるかもしれません。  
`using System.Text.Json.Serialization;`を追加して以下のどれかを使ってみてください。  
ただし微妙に使い勝手が違う可能性があります。

[シリアル化からプロパティを除外する](https://docs.microsoft.com/ja-
jp/dotnet/standard/serialization/system-text-json-how-to#exclude-properties-
from-serialization)

> 既定では、すべてのパブリックプロパティがシリアル化されます。 一部のオプションが JSON
> 出力に表示されないようにするには、いくつかのオプションがあります。 ここでは、を除外する方法について説明します。
>
>   * 個々のプロパティ  
>  個々のプロパティを無視するには、 [[JsonIgnore]](https://docs.microsoft.com/ja-
> jp/dotnet/api/system.text.json.serialization.jsonignoreattribute)属性を使用します。  
>  ＜以下コーディング例の一部＞
>

```

    public class WeatherForecastWithIgnoreAttribute
    {
          public DateTimeOffset Date { get; set; }
        public int TemperatureCelsius { get; set; }
        [JsonIgnore]
        public string Summary { get; set; }
    }
    
```

>   * すべての読み取り専用プロパティ  
>  パブリックゲッターが含まれていてもパブリック setter がない場合、プロパティは読み取り専用です。
> すべての読み取り専用プロパティを除外するには、次の例に示すように、[JsonSerializerOptions.IgnoreReadOnlyProperties](https://docs.microsoft.com/ja-
> jp/dotnet/api/system.text.json.jsonserializeroptions.ignorereadonlyproperties#System_Text_Json_JsonSerializerOptions_IgnoreReadOnlyProperties)を`true`に設定します。  
>  このオプションは、シリアル化にのみ適用されます。 逆シリアル化中、読み取り専用プロパティは既定では無視されます。  
>  ＜以下コーディング例の一部＞
>

```

    var options = new JsonSerializerOptions
    {
        IgnoreReadOnlyProperties = true,
        WriteIndented = true
    };
    jsonString = JsonSerializer.Serialize(weatherForecast, options);
    
    public class WeatherForecastWithROProperty
    {
        public DateTimeOffset Date { get; set; }
        public int TemperatureCelsius { get; set; }
        public string Summary { get; set; }
        public int WindSpeedReadOnly { get; private set; } = 35;
    }
    
```

>   * すべての null 値プロパティ  
>  すべての null
> 値プロパティを除外するには、次の例に示すように、[IgnoreNullValues](https://docs.microsoft.com/ja-
> jp/dotnet/api/system.text.json.jsonserializeroptions.ignorenullvalues#System_Text_Json_JsonSerializerOptions_IgnoreNullValues)プロパティを`true`に設定します。  
>  この設定は、シリアル化と逆シリアル化に適用されます。 逆シリアル化に対する影響については、[「逆シリアル化するときに null
> を無視する」](https://docs.microsoft.com/ja-
> jp/dotnet/standard/serialization/system-text-json-how-to#ignore-null-when-
> deserializing)を参照してください。  
>  ＜以下コーディング例の一部＞
>

```

    var options = new JsonSerializerOptions
    {
        IgnoreNullValues = true,
        WriteIndented = true
    };
    jsonString = JsonSerializer.Serialize(weatherForecast, options);
    
```

* * *

微妙かも？というのはこういうIssueを見つけたので。何か影響があるのかもしれません。

[System.Text.Json.JsonSerializer can't deserialize readonly collection
property #31015](https://github.com/dotnet/runtime/issues/31015)  
[Support adding to collections if no setter
#30258](https://github.com/dotnet/runtime/issues/30258)

* * *

出来るかどうか分かりませんが、希望する機能のカスタムコンバーターを作って適用するとか。

[カスタムコンバーターを登録する](https://docs.microsoft.com/ja-
jp/dotnet/standard/serialization/system-text-json-converters-how-to#register-
a-custom-converter)

> カスタムコンバーターを登録して、Serialize および Deserialize メソッドで使用されるようにします。 次のいずれかの方法を選択します。
>
>   * コンバータークラスのインスタンスを[JsonSerializerOptions.Converters
> プロパティ](https://docs.microsoft.com/ja-
> jp/dotnet/api/system.text.json.jsonserializeroptions.converters?view=netcore-3.1)
> コレクションに追加します。
>   * カスタムコンバーターを必要とするプロパティに[jsonconverter](https://docs.microsoft.com/ja-
> jp/dotnet/api/system.text.json.serialization.jsonconverterattribute?view=netcore-3.1)属性を適用します。
>   * [Jsonconverter](https://docs.microsoft.com/ja-
> jp/dotnet/api/system.text.json.serialization.jsonconverterattribute?view=netcore-3.1)属性をカスタム値型を表すクラスまたは構造体に適用します。
>

[その他のカスタムコンバーターのサンプル](https://docs.microsoft.com/ja-
jp/dotnet/standard/serialization/system-text-json-converters-how-to#other-
custom-converter-samples)

> [Newtonsoft.Json から System.Text.Jsonへの移行](https://docs.microsoft.com/ja-
> jp/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-
> how-to)に関する記事には、カスタムコンバーターの追加のサンプルが含まれています。  
>  System.Text.Json.Serialization
> ソースコードの[単体テストフォルダー](https://github.com/dotnet/runtime/blob/81bf79fd9aa75305e55abe2f7e9ef3f60624a3a1/src/libraries/System.Text.Json/tests/Serialization/)には、次のような他のカスタムコンバーターのサンプルが含まれています。
>
>
> 既存の組み込みコンバーターの動作を変更するコンバーターを作成する必要がある場合は、[既存のコンバーターのソースコード](https://github.com/dotnet/runtime/tree/81bf79fd9aa75305e55abe2f7e9ef3f60624a3a1/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters)を取得して、カスタマイズの開始点として機能させることができます。

関連があるかどうかも不明ですがこんな記事も。  
[C# で定義が未知の Json を扱う (.NET Framework / .NET Core)
まとめ](https://rksoftware.hatenablog.com/entry/2020/02/12/212643)

> ■ System.Text.Json.JsonSerializer.Deserialize  
>  ■ やっぱり System.Text.Json でも System.Dynamic.ExpandoObject を使いたい
CC BY-SA 4.0
2020-03-18T06:39:58.520
63956
2020-03-18T09:10:15.360
2020-03-18T09:10:15.360
26370
26370
63954
answer
System.Text.Json 5.0.0 で `[JsonIgnore(Condition =
JsonIgnoreCondition.WhenWritingDefault)]`
属性でデフォルト値の場合に書き込み無効にすることができるようになりました。
CC BY-SA 4.0
2020-12-16T03:31:52.577
72681
2020-12-16T03:31:52.577
14817
63954
answer