Json.Netのプライベートセッター


93

プライベートセッターを処理する属性があることは知っていますが、この動作をデフォルトとして設定したいのですが、これを実現する方法はありますか?ソースの微調整を除きます。これのための設定があったら素晴らしいでしょう。


1
私はこれその答えを探していました。
marbel82 2017

回答:


112

ここに来て、逆シリアル化時に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; }

19
ほんの小さなメモ:それはで{get;private set;}はなくで動作します{get;}
チムタム2017

8
ほんの少し更新。現在は{get;}でも機能します。
HAV

1
@Havそれ以降のバージョンは?私はv11.0.2をテストしたばかりで動作しませ {get;}
tymtam

1
@tymtamこれは{ get; }、型に、プロパティ名と一致するパラメーターを持つコンストラクターがある場合にのみ機能すると思います。
Saeb Amini、2018

2
@tymtamは、この代替案と例を使用して回答を更新しました。
Saeb Amini、2018

77

更新された、新しい答え

このためのソースディストリビューションNuGetを作成しました。これは、2つのカスタムコントラクトリゾルバーを含む単一のファイルをインストールします。

  • PrivateSetterContractResolver
  • PrivateSetterCamelCasePropertyNamesContractResolver

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/



1
@Jafin urlは死にました、danielwertheim.wordpress.com / 2010/11/06 /…それは今それを持っています
Chris Marisic

1
以下のように見えるAltキー2は間違いなく、今日行く方法です。廃止DefaultMembersSearchFlagsれました
Todd Menier、2015年

4
c#6では、{get; }はと同等ではありません{ get; private set; }。最初の方法でproperty.GetSetMethod(true)は戻りnull、後者では戻りますtrue。これには驚きました。private set;逆シリアル化が期待どおりに機能するために必要です。
16年

Install-Package JsonNet.ContractResolversを使用する必要があるようです。github.com/danielwertheim/jsonnet-contractresolvers
同盟

14

@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()
};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.