プライベートセッターを処理する属性があることは知っていますが、この動作をデフォルトとして設定したいのですが、これを実現する方法はありますか?ソースの微調整を除きます。これのための設定があったら素晴らしいでしょう。
回答:
ここに来て、逆シリアル化時にJson.NETに読み取り専用プロパティを設定させる実際の属性を探しました[JsonProperty]。
[JsonProperty]
public Guid? ClientId { get; private set; }
プロパティに一致するパラメーターを持つコンストラクターを提供するだけです。
public class Foo
{
public string Bar { get; }
public Foo(string bar)
{
Bar = bar;
}
}
これでうまくいきます:
string json = "{ \"bar\": \"Stack Overflow\" }";
var deserialized = JsonConvert.DeserializeObject<Foo>(json);
Console.WriteLine(deserialized.Bar); // Stack Overflow
私は可能な限りこのアプローチを好みます:
{ get; private set; }し、ちょうど{ get; }。{get;private set;}はなくで動作します{get;}
{ get; }、型に、プロパティ名と一致するパラメーターを持つコンストラクターがある場合にのみ機能すると思います。
このためのソースディストリビューションNuGetを作成しました。これは、2つのカスタムコントラクトリゾルバーを含む単一のファイルをインストールします。
NuGetをインストールします。
Install-Package JsonNet.PrivateSettersContractResolvers.Source
次に、任意のリゾルバーを使用します。
var settings = new JsonSerializerSettings
{
ContractResolver = new PrivateSetterContractResolver()
};
var model = JsonConvert.DeserializeObject<Model>(json, settings);
あなたはそれについてここで読むことができます:http://danielwertheim.se/json-net-private-setters-nuget/
GitHubリポジトリ:https : //github.com/danielwertheim/jsonnet-privatesetterscontractresolvers
この問題を解決する方法は2つあります。
Alt 1:デシリアライザについて
ContractResolver.DefaultMembersSearchFlags =
DefaultMembersSearchFlags | BindingFlags.NonPublic;
デフォルトのシリアル化オプションは、すべてのタイプのクラスメンバーをサポートします。したがって、このソリューションはフィールドを含むすべてのプライベートメンバータイプを返します。私はプライベートセッターのサポートにも関心があります。
Alt2:カスタムContractResolverを作成します。
したがって、プロパティをチェックするだけなので、これはより良いオプションです。
public class SisoJsonDefaultContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(
MemberInfo member,
MemberSerialization memberSerialization)
{
//TODO: Maybe cache
var prop = base.CreateProperty(member, memberSerialization);
if (!prop.Writable)
{
var property = member as PropertyInfo;
if (property != null)
{
var hasPrivateSetter = property.GetSetMethod(true) != null;
prop.Writable = hasPrivateSetter;
}
}
return prop;
}
}
詳細については、私の投稿を読んでください:http : //danielwertheim.se/json-net-private-setters/
{get; }はと同等ではありません{ get; private set; }。最初の方法でproperty.GetSetMethod(true)は戻りnull、後者では戻りますtrue。これには驚きました。private set;逆シリアル化が期待どおりに機能するために必要です。
@Danielの答え(Alt2)は適切ですが、プライベートセッターとゲッターの両方で機能するためにこれが必要でした(私は、実際にのようないくつかの書き込み専用のものを持つAPIで作業していますuser.password)。
public class NonPublicPropertiesResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {
var prop = base.CreateProperty(member, memberSerialization);
if (member is PropertyInfo pi) {
prop.Readable = (pi.GetMethod != null);
prop.Writable = (pi.SetMethod != null);
}
return prop;
}
}
このように登録:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
ContractResolver = new NonPublicPropertiesResolver()
};